[英]how to access rails join model attributes when using has_many :through
I have a data model something like this: 我有一个像这样的数据模型:
# columns include collection_item_id, collection_id, item_id, position, etc
class CollectionItem < ActiveRecord::Base
self.primary_key = 'collection_item_id'
belongs_to :collection
belongs_to :item
end
class Item < ActiveRecord::Base
has_many :collection_items
has_many :collections, :through => :collection_items, :source => :collection
end
class Collection < ActiveRecord::Base
has_many :collection_items, :order => :position
has_many :items, :through => :collection_items, :source => :item, :order => :position
end
An Item can appear in multiple collections and also more than once in the same collection at different positions. 一个项目可以出现在多个集合中,也可以在同一集合中的不同位置出现多次。
I'm trying to create a helper method that creates a menu containing every item in every collection. 我正在尝试创建一个辅助方法,该方法创建一个包含每个集合中每个项目的菜单。 I want to use the collection_item_id to keep track of the currently selected item between requests, but I can't access any attributes of the join model via the Item class. 我想使用collection_item_id跟踪请求之间当前选择的项目,但是我无法通过Item类访问联接模型的任何属性。
def helper_method( collection_id )
colls = Collection.find :all
colls.each do |coll|
coll.items.each do |item|
# !!! FAILS HERE ( undefined method `collection_item_id' )
do_something_with( item.collection_item_id )
end
end
end
I tried this as well but it also fails with ( undefined method `collection_item' ) 我也尝试过此操作,但也失败了(未定义的方法`collection_item')
do_something_with( item.collection_item.collection_item_id )
Edit: thanks to serioys sam for pointing out that the above is obviously wrong 编辑:感谢serioys sam指出以上内容显然是错误的
I have also tried to access other attributes in the join model, like this: 我还尝试访问联接模型中的其他属性,如下所示:
do_something_with( item.position )
and: 和:
do_something_with( item.collection_item.position )
Edit: thanks to serioys sam for pointing out that the above is obviously wrong 编辑:感谢serioys sam指出以上内容显然是错误的
but they also fail. 但他们也失败了。
Can anyone advise me how to proceed with this? 谁能告诉我如何进行此操作?
Edit: --------------------> 编辑:-------------------->
I found from online documentation that using has_and_belongs_to_many will attach the join table attributes to the retreived items, but apparently it is deprecated. 我从在线文档中发现,使用has_and_belongs_to_many会将联接表属性附加到检索到的项上,但显然已弃用。 I haven't tried it yet. 我还没有尝试过。
Currently I am working on amending my Collection model like this: 目前,我正在像这样修改我的收藏模型:
class Collection < ActiveRecord::Base
has_many :collection_items, :order => :position, :include => :item
...
end
and changing the helper to use coll.collection_items instead of coll.items 并将助手更改为使用coll.collection_items而不是coll.items
Edit: --------------------> 编辑:-------------------->
I've changed my helper to work as above and it works fine - (thankyou sam) 我已经更改了助手的工作方式,使其可以正常工作-(谢谢Sam)
It's made a mess of my code - because of other factors not detailed here - but nothing that an hour or two of re-factoring wont sort out. 由于没有在此详细说明的其他因素,这使我的代码一团糟-但一两个小时的重构无法解决。
In your example you have defined in Item model relationship as has_many for collection_items and collections the generated association method is collection_items and collections respectively both of them returns an array so the way you are trying to access here is wrong. 在您的示例中,您已经在Item模型关系中为collection_items和collections定义了has_many,所生成的关联方法是collection_items和collections两者都返回一个数组,因此您在此处尝试访问的方式是错误的。 this is primarily case of mant to many relationship. 这主要是许多关系的情况。 just check this Asscociation Documentation for further reference. 只需查看此《 Asscociation文档》以获取更多参考。
do_something_with( item.collection_item_id )
This fails because item does not have a collection_item_id member. 这失败,因为项目没有collection_item_id成员。
do_something_with( item.collection_item.collection_item_id )
This fails because item does not have a collection_item member. 这失败,因为item没有collection_item成员。
Remember that the relation between item and collection_items is a has_many. 请记住,item和collection_items之间的关系是has_many。 So item has collection_items, not just a single item. 因此item具有collection_items,而不仅仅是单个item。 Also, each collection has a list of collection items. 此外,每个集合都有一个集合项列表。 What you want to do is probably this: 您想要做的可能是这样的:
colls = Collection.find :all
colls.each do |coll|
coll.collection_items.each do |collection_item|
do_something_with( collection_item.id )
end
end
A couple of other pieces of advice: 其他一些建议:
I found from online documentation that using has_and_belongs_to_many will attach the join table attributes to the retreived items, but apparently it is deprecated. 我从在线文档中发现,使用has_and_belongs_to_many会将联接表属性附加到检索到的项上,但显然已弃用。 I haven't tried it yet. 我还没有尝试过。
I recommend you stick with has_many :through, because has_and_belongs_to_many is more confusing and doesn't offer any real benefits. 我建议您坚持使用has_many:through,因为has_and_belongs_to_many更加令人困惑,并且没有任何真正的好处。
I was able to get this working for one of my models: 我能够在我的其中一个模型中使用此功能:
class Group < ActiveRecord::Base
has_many :users, :through => :memberships, :source => :user do
def with_join
proxy_target.map do |user|
proxy_owner = proxy_owner()
user.metaclass.send(:define_method, :membership) do
memberships.detect {|_| _.group == proxy_owner}
end
user
end
end
end
end
In your case, something like this should work (haven't tested): 在您的情况下,类似这样的方法应该起作用(未经测试):
class Collection < ActiveRecord::Base
has_many :collection_items, :order => :position
has_many :items, :through => :collection_items, :source => :item, :order => :position do
def with_join
proxy_target.map do |items|
proxy_owner = proxy_owner()
item.metaclass.send(:define_method, :join) do
collection_items.detect {|_| _.collection == proxy_owner}
end
item
end
end
end
end
Now you should be able to access the CollectionItem from an Item as long as you access your items like this ( items.with_join
): 现在,只要您访问这样的项目( items.with_join
),就应该可以从Item中访问CollectionItem:
def helper_method( collection_id )
colls = Collection.find :all
colls.each do |coll|
coll.items.with_join.each do |item|
do_something_with( item.join.collection_item_id )
end
end
end
Here is a more general solution that you can use to add this behavior to any has_many :through
association: http://github.com/TylerRick/has_many_through_with_join_model 这是一个更通用的解决方案,可用于将这种行为添加到任何has_many :through
关联: http : //github.com/TylerRick/has_many_through_with_join_model
class Collection < ActiveRecord::Base
has_many :collection_items, :order => :position
has_many :items, :through => :collection_items, :source => :item, :order => :position, :extend => WithJoinModel
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.