2012-03-15 13 views
9

Ruby on Railsプロジェクトすべてをデータベースに保存する前に、ActiveRecordの関連オブジェクトにアクセスしようとしています。Ruby on Railsで保存する前に関連オブジェクトをhas_manyで保存する

class Purchase < ActiveRecord::Base 

    has_many :purchase_items, dependent: :destroy 
    has_many :items, through: :purchase_items 

    validate :item_validation 

    def item_ids=(ids) 
    ids.each do |item_id| 
     purchase_items.build(item_id: item_id) 
    end 
    end 

    private 

    def item_validation 
    items.each do |item| 
     ## Lookup something with the item 
     if item.check_something 
     errors.add :base, "Error message" 
     end 
    end 
    end 

end 

ので、同様に、私は私のオブジェクトを構築した場合: purchase = Purchase.new(item_ids: [1, 2, 3])item_validation方法は、アイテムコレクションがまだ読み込まれていないので、アイテムが設定されているにもかかわらず、それを保存しようとするが、それは取得しない設定それらのいずれかでcheck_somethingメソッドを呼び出すチャンス。

購入モデルと関連モデルが永続化される前にアイテムコレクションにアクセスして、そのモデルに対して検証を実行できますか?

私がそれをしたいように動作するように思わ
def item_validation 
    purchase_items.each do |purchase_item| 
    item = purchase_item.item 
    ## Lookup something with the item 
    if item.something 
     errors.add :base, "Error message" 
    end 
    end 
end 

、しかし私はそれが難しい直接でのアイテムのコレクションにアクセスする方法がないことを信じることを見つける:

私はあることを私のitem_validation方法を変更した場合購入前のレールと関連レコードがデータベースに保存されます。

答えて

0

purchase = Purchase.new(item_ids: [1, 2, 3])は、あなたが期待していることを示す文書がありますか?

非データベース属性 'item_ids'を配列に設定するだけです(つまり、関連付けを作成しない)ようです。

あなたの購入モデルには、直接設定する外部キー列があってはいけません。代わりに、purchase_iditem_idを持つエントリがpurchase_itemsテーブルにあります。購入と3つのアイテム間のリンクを作成するには、結合ツールテーブルに3つのエントリを作成する必要があります。あなただけではなく、あなたがmodel.associations = [association_objects]を使用することができます

purchase = Purchase.new 
purchase.items = Item.find([1,2,3]) 
1

はinverse_of引数を追加してみてください:has_manyの中や定義BELONGS_TO。それは他のモデルにリレーションの名前だinverse_of引数には、例えば:

class Post < ActiveRecord::Base 
    has_many :comments, inverse_of: :post 
end 

class Comment < ActiveRecord::Base 
    belongs_to :post, inverse_of: :comments 
end 

は、購入アイテムなど他のクラス、上にもそれを追加することを忘れてはいけないとItem

は、それが

を役に立てば幸い
1

独自のitem_ids=メソッドを削除します。これは、railsが自動的に生成します(collection_singular_ids=idsを参照)。これはすでにあなたの問題を解決するかもしれません。あなたのコードを見て私の心に来る

class Purchase < ActiveRecord::Base 

    has_many :purchase_items, dependent: :destroy 
    has_many :items, through: :purchase_items 

    validate :item_validation 

    private 

    def item_validation 
    items.each do |item| 
     ## Lookup something with the item 
     if item.check_something 
     errors.add :base, "Error message" 
     end 
    end 
    end 

end 

二つ目:Itemクラスに検証を移動します。だから、:Item Sのいずれかが無効である場合

class Purchase < ActiveRecord::Base 
    has_many :purchase_items, dependent: :destroy 
    has_many :items, through: :purchase_items 
end 

class Item < ActiveRecord::Base 
    has_many :purchase_items 
    has_many :purchases, through: :purchase_items 

    validate :item_validation 

    private 

    def item_validation 
     if check_something 
     errors.add :base, "Error message" 
     end 
    end 
end 

あなたPurchaseのレコードも無効になります。

0

idPurchaseのため、アクセスできないと思われます。レコードを保存する前にアクセスできません。しかし、あなたは、あなたが最初のレベルの協会purchase_itemsへのアクセス権を持っているので、あなたはすべてのIDを抽出し、Itemためwhereでそれらを渡すことができます言及として:

items = Item.where(purchase_item_id: purchase_items.map(&:id)) 
関連する問題