Ruby on Rails在保存之前通过关联对象具有很多function
在Ruby on Rails项目上,我试图在将所有内容保存到数据库之前访问ActiveRecord上的关联对象。
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
方法还没有填充items集合,所以即使已经设置了项目设置它没有机会在任何一个上调用check_something
方法。
是否可以在我的购买模型和关联模型持久化之前访问项目集合,以便我可以对它们运行validation?
如果我将item_validation
方法更改为:
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
它似乎以我想要的方式工作,但是我发现很难相信在我购买之前没有办法直接访问带有rails的items集合,并且相关记录被保存到数据库中。
尝试在has_many和belongs_to定义中添加参数inverse_of :. inverse_of参数它是另一个模型上关系的名称,例如:
class Post < ActiveRecord::Base has_many :comments, inverse_of: :post end class Comment < ActiveRecord::Base belongs_to :post, inverse_of: :comments end
不要忘记将其添加到其他类上,例如PurchaseItem和Item
希望能帮助到你
删除你自己的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
我想到的第二件事是看你的代码:将validation移到Item
类。 所以:
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
如果其中一个Item
无效,您的Purchase
记录也将无效。
你有文件表明purchase = Purchase.new(item_ids: [1, 2, 3])
你做了什么?
对我来说,看起来你只是将非数据库属性’item_ids’设置为一个数组(即不创建关联)。
您的购买模型甚至不应该直接设置任何外键列。 相反, purchase_items
表中的条目具有purchase_id
和item_id
。 要在购买和三个项目之间创建链接,您需要在joiner表中创建三个条目。
如果你这样做会发生什么?:
purchase = Purchase.new purchase.items = Item.find([1,2,3])
您可以使用model.associations = [association_objects]
和Association Callback
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Association+callbacks
我假设您无法访问它们,因为在保存记录之前,“ Purchase
id
不可用。 但正如您所提到的,您可以访问第一级关联purchase_items
,因此您可以提取所有ID并将其传递到Item
:
items = Item.where(purchase_item_id: purchase_items.map(&:id))