2017-01-31 3 views
1

親のbefore_saveコールバックで子レコードを変更する際に苦労しています。before_saveコールバックの子レコードを変更する

子レコードは、mainというブール値の属性を持つPhotoです。

親レコードはhas_many :photos

レコードを変更するためのフォームがdealに変更を加えるためにネストされていると、ユーザーはまた、photoの属性を変更したり、追加したり、photosを削除することができDealです。

ここには擦れがあります。私はいつもmainの写真を持っている必要があります。私は写真をチェックするbefore_saveコールバックでこれを行う予定です。リストにはmainの写真がない場合は、リストの最初の写真にtrueを設定します。

子レコードを保存していないので、それを期待しています。私はメソッドが呼び出されていることを証明できるようにデバッグ文を追加しました。また、mainの値がtrueとマークされていることを示すこともできます。私はこのコールバックを誤解していますか?軽い倉庫は素晴らしいでしょう。みんなありがとう!

class Deal < ActiveRecord::Base 

    has_many :photos, dependent: :destroy 
    accepts_nested_attributes_for :photos, allow_destroy: :true 

    before_save :set_main_photo 


    ### bunch of other unrelated stuff 

    private 
    def set_main_photo 
    if self.photos 
     if self.photos.main.nil? 
     self.photos.first.main = true 
     end 
    end 
    end 
end 

答えて

2

ここではいくつかのことが起こりますが、主な問題はこの方法で子を変更しても自動的にレコードが保存されないことです。子レコードの.saveを呼び出すようにset_main_photoを更新する必要があります。あなたはそれに取り組んでいる一方で、他のいくつかの変更が賢明です:あなたは今の関係の状態とを表すPhotoの属性を持っている厄介な方法でDealPhotosを結合しましたが、行ってこれにより

def set_main_photo 
    if photos.any? 
    unless photos.main.present? 
     photos.first.update_attribute :main, true 
    end 
    end 
end 

その属性を管理するDealおよびDealより良いアプローチは、完全にDeal内の属性のための責任を保ち、これをモデル化するための新たな関係を作成するために、次のようになります。

class Deal 
    has_many :photos 
    belongs_to :main_photo, class_name: 'Photo' 
end 

class Photo 
    belongs_to :deal 
end 

これは、あなたは、単にdeal.main_photo = deal.photos.firstを設定し、deal.saveすることができます。

+1

最初の例は、取引が既に永続化されている場合にのみ機能します。代わりに 'assign_attribute'を使用することで救済することができます。しかし、後の例は最初の方が良いアイデアです。 – max

関連する問題