2016-11-29 3 views
1

関連するオブジェクトの数をチェックするカスタム検証に問題があります。 EventGuestの2つのクラスがあります。作成時および更新時に異なる動作をする関連オブジェクトの検証

ユーザーが新しいイベントを作成すると、招待するゲストを選択できます。保存すると、招待されたゲストの数を確認したいと思います。

既存のイベントを更新するときに検証が正常に機能します。しかし、新しいイベントの作成時にself.guests.count0を返すので、検証は失敗します。 コントローラで、私は選択したゲストが同じ方法でモデルに渡されたことを確認しました:params[:event][:guest_ids]

更新の場合、妥当性確認ブロックが呼び出される前にアソシエーションテーブルを更新するSQL INSERT INTOがトランザクションキューに追加されていることがわかります。新しいイベントが発生した場合は、検証が失敗する前にSQL INSERTが表示されません。

私はここで何が欠けていますか?いくつかの回避策について考えていましたが、これを実装する適切な方法があると確信しています。

Railsのバージョンは4.2.6

class Event < ActiveRecord::Base 
    has_and_belongs_to_many :guests 
    validate :check_guestlist 

    def check_guestlist 
    guest_count=self.guests.count 
    if guest_count < 3 
     errors.add(“Please invite more guests”) 
    end 
    end 

class Guest < ActiveRecord::Base 
    has_and_belongs_to_many :events 
end 


class EventsController < ApplicationController 
    def create 
    @event = current_user.events.new(event_params) 

    respond_to do |format| 
     if @event.save 
     format.html { redirect_to @event, notice: 'Event was successfully created.' } 
     else 
     flash.now[:alert]='Event not saved.' 
     format.html { render action: "new" } 
     end 
    end 
    end 

    def update 
    @event = current_user.events.find(params[:id]) 

    respond_to do |format| 
     if @event.update_attributes(event_params) 
     format.html { redirect_to @event, notice: 'Event was successfully updated.' } 
     else 
     flash.now[:alert]='Changes not saved.' 
     format.html { render action: "edit" } 
     end 
    end 
    end 
end 
+0

イベントモデルのゲスト用にaccept_nested_attributesを追加してみてください。エラーが解決しない場合は、コントローラのメソッドとフォームを追加してください。 – Zero

+0

ありがとう!私は 'accepts_nested_attributes_for:guests'を追加しようとしましたが、それは助けになりませんでした。コントローラーコードが元の質問に追加されました。 – Peb

答えて

0

私はカスタム検証のコードの行を置き換えることによって、この問題を回避するために管理しています。 私は

guest_count=self.guests.to_a.count 

guest_count=self.guests.count 

を交換した場合、私は期待どおりの結果を得ることができます。 更新の場合、両方の式が同じ結果を返します。しかし、新しい記録の文脈では、第2のものだけが期待どおりに応答する。 それでも、最初のバージョンが動作しなかった理由はまだ分かりません。

0

いいえself.guests.countが作成時に機能しない理由は、実際にはイベントのスコープを持つデータベースクエリを実行しているということです。

SELECT COUNT(*) FROMゲストWHEREゲスト.は今

= 1をEVENT_IDゲストが保存されている前に検証が発生するので、もちろん、これは失敗します。今更新すると、データベースに見つかるエントリがあるために動作します。しかし、検証は間違った情報と照合しているため、データベース内のゲストの数は必ずしもself.guestの数と一致しません。ゲストをもう1人追加できましたが、まだ保存されていません。

あなたのソリューションは、作業を行いますが、個人的に、私はそれのようにそれを書くために良いだろうと思う:

validates :guests, length: { minimum: 3, message: 'Please invite more guests' } 

lengthは、ゲストの配列のサイズをテストします - 例えばself.guests.lengthは事実上同じですself.guests.to_a.count

+0

こんにちはDavidさん、ありがとうございました。しかし、私は、更新の場合、「間違った情報をチェックしています」というあなたの声明には同意しません。これは事実ではなく、頭痛を引き起こします。 更新の場合、検証の前にデータベースの更新がトランザクションキューに入れられ、検証が成功することがわかりました。私はこれを実際のアプリケーションでテストし、アップデートの場合にはうまくいきました! – Peb

+0

それを試してみましょう... Railsコンソールで3人のゲストと一緒にイベントを作成して保存します。 'event.guests.count'をチェックする...これは3になります....他のゲストをイベントに追加して、今は' event.guests.count'を呼び出します.SQLクエリの実行とその結果が表示されます – David

+0

私は正しい結果(あなたの例では= 4)を得ていますが、これはトランザクションにINSERT INTOステートメントがあるため意味があります検証が行われる前に待機してください。 私は非常に困惑しています...特に私が実装した回避策が機能しているためです... – Peb

関連する問題