简体   繁体   English

使用has_many时如何访问rails join模型属性:through

[英]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: 其他一些建议:

  • Have you read the documentation for has_many :through in the Rails Guides? 您是否已阅读《 Rails指南》中has_many文档 It is pretty good. 很好
  • You shouldn't need the :source parameters in the has_many declarations, since you have named your models and associations in a sensible way. 在has_many声明中,您不需要:source参数,因为您已经以一种明智的方式命名了模型和关联。

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.

相关问题 在rails has_many中使用join模型属性:through - using join model attributes in rails has_many :through Rails has_many:通过在联接模型中按附加属性查找 - Rails has_many :through Find by Extra Attributes in Join Model 在提交嵌套表单时,Rails has_many通过连接模型undefined id:“undefined方法`属性&#39;为#” - Rails has_many through join model undefined id: “undefined method `attributes' for #” when submitting nested form Rails-使用group_by和has_many:through并尝试访问联接表属性 - Rails - using group_by and has_many :through and trying to access join table attributes Rails嵌套表单与has_many:through,如何编辑连接模型的属性? - Rails nested form with has_many :through, how to edit attributes of join model? 如何在has_many:through关联中访问联接模型的属性 - How do I access attributes of the join model in a has_many :through association 如何在has_many中获取模型的属性:通过Rails 5中的关联 - How to get attributes of model in has_many :through association in Rails 5 Rails - 在 has_many 上使用 join model 过滤 - Rails - filter using join model on has_many through 使用has_many:through时,连接模型中的验证失败 - Failing validations in join model when using has_many :through Ruby on Rails:当联接模型使用belongs_to时,如何通过关联来构造has_many - Ruby on Rails: How to structure a has_many, through association when join model uses a belongs_to
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM