:多态/:通过ActiveRecord关联(Rails的3.2) [英] :polymorphic/:through ActiveRecord associations (Rails 3.2)
问题描述
我有一个可以适用于不同的 Taggable
s的标签系统。我希望能够查询它们透明,在这里接受的解决方案:
我想可以说,例如,告诉我所有的发表
S,页
S,视频
S等标记为'富'。 pretty的straighforward。并发症:
- 在不同种类的
Taggable的
是不是多态的面向对象的意义上说,只有通过多态关联。这里的是的一个taggables
表,以保证taggable_id的唯一性(在帖主键
,等等)。 -
标签
S,这并不奇怪,有一个多到许多关系与Taggable
s和关联通过map_tags
表。
型号:
类标签<的ActiveRecord :: Base的
的has_many:map_tags
的has_many:标签,:通过=> :map_tags
结束
类MapTag<的ActiveRecord :: Base的
belongs_to的:标签
belongs_to的:标记,多态=> :真正
结束
类岗位<的ActiveRecord :: Base的
的has_many:map_tags,:为=> :标签
的has_many:标签,:通过=> :map_tags
#其他taggables都设置了类似
结束
问题:
- 我想我的第一个问题应该是:这甚至可能吗?我所看到的模型有很多相关的情况下多态,但我不知道它的工作原理的其他方式,如错误消息下方可能会建议...
- 难道我设置了多态是否正确?我的理解是,儿童模式基本上宣布自己为标记,并与他们取表接口直接(在这种情况下,
map_tags
)是一个得到了:多态
声明 - 如何说告诉我一切都标记为'富'中的ActiveRecord-说话?
我已经试过什么:
IRB> Tag.find_by_name('富',:包括=>:标签)
标记加载(0.1毫秒)选择`tags`。* FROM`tags` WHERE`tags`.`name` ='富'LIMIT 1
NameError:未初始化的常数标签::标记
...
IRB> Tag.find(:所有,:包括=>:标签,:条件=>Tag.name ='富'])
ActiveRecord的:: HasManyThroughAssociationPolymorphicSourceError:
能不能有一个的has_many:通过关联标签#标签为多态对象标签#标签。
...
修改
我发现<一href="http://stackoverflow.com/questions/6997141/rails-has-many-through-with-polymorphic-association-will-this-work">this帖子,其中指出,我需要指定:源
和:SOURCE_TYPE
。所以:
类标签&lt;的ActiveRecord :: Base的
的has_many:map_tags
的has_many:帖子,:通过=&GT; :map_tags,:源=&GT; :标记,:SOURCE_TYPE =&GT; 邮报
的has_many:页面:通过=&GT; :map_tags,:源=&GT; :标记,:SOURCE_TYPE =&GT; '页'
结束
我觉得我更近(?),但我仍然不知道如何查询相关联的对象...
IRB&GT; Tag.first.posts
标记加载(为0.2ms)选择`tags`。* FROM`tags`限制1
NoMethodError:未定义的方法`帖的#&LT;标签ID:1,名称:福&GT;
IRB&GT; Tag.first.tagged
标记加载(为0.2ms)选择`tags`。* FROM`tags`限制1
ActiveRecord的:: HasManyThroughAssociationPolymorphicSourceError:
能不能有一个的has_many:通过关联标签#标签为多态对象标签#标签。
您多态关联的设置是否正确。除了一个小错字:
belongs_to的:标记,多态=&GT; :真正
这应该是真实的布尔不是:真正的象征
!I have a tag system that can apply to various Taggable
s. I want to be able to query them transparently, as in the accepted solution here:
HABTM Polymorphic Relationship
I want to be able to say, for example, show me all Post
s, Page
s, Video
s, etc. tagged with 'foo'. Pretty straighforward. The complications:
- The different kinds of
Taggable
s are not polymorphic in the OO sense, only through polymorphic associations. There is ataggables
table to guarantee uniqueness of taggable_id (the primary key inposts
, etc.). Tag
s, not surprisingly, have a many-to-many relation withTaggable
s, and are associated through themap_tags
table.
Models:
class Tag < ActiveRecord::Base
has_many :map_tags
has_many :tagged, :through => :map_tags
end
class MapTag < ActiveRecord::Base
belongs_to :tags
belongs_to :tagged, :polymorphic => :true
end
class Post < ActiveRecord::Base
has_many :map_tags, :as => :tagged
has_many :tags, :through => :map_tags
# other taggables are set up similarly
end
Questions:
- I guess my first questions ought to be: is this even possible? I have seen Models "have many" associated instances polymorphically, but I'm not sure if it works the other way, as the error message below may suggest...
- Did I set up the polymorphism correctly? My understanding is that the "child" models basically declare themselves as "tagged", and whichever table interfaces with them directly (in this case
map_tags
) is the one to get the:polymorphic
declaration. - How do I say "show me everything tagged with 'foo'" in ActiveRecord-speak?
What I've tried:
irb> Tag.find_by_name( 'foo', :include => :tagged )
Tag Load (0.1ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`name` = 'foo' LIMIT 1
NameError: uninitialized constant Tag::Tagged
...
irb> Tag.find( :all, :include => :tagged, :conditions => ["Tag.name = 'foo'"] )
ActiveRecord::HasManyThroughAssociationPolymorphicSourceError:
Cannot have a has_many :through association 'Tag#tagged' on the polymorphic object 'Tagged#tagged'.
...
EDIT
I found this post, which points out that I need to specify :source
and :source_type
. So:
class Tag < ActiveRecord::Base
has_many :map_tags
has_many :posts, :through => :map_tags, :source => :tagged, :source_type => 'Post'
has_many :pages, :through => :map_tags, :source => :tagged, :source_type => 'Page'
end
I think I'm closer(?), but I'm still not sure how to query the associated objects...
irb> Tag.first.posts
Tag Load (0.2ms) SELECT `tags`.* FROM `tags` LIMIT 1
NoMethodError: undefined method `posts' for #<Tag id: 1, name: "foo">
irb> Tag.first.tagged
Tag Load (0.2ms) SELECT `tags`.* FROM `tags` LIMIT 1
ActiveRecord::HasManyThroughAssociationPolymorphicSourceError:
Cannot have a has_many :through association 'Tag#tagged' on the polymorphic object 'Tagged#tagged'.
Your polymorphic association setup is correct. Except for a small typo :
belongs_to :tagged, :polymorphic => :true
It should be true the boolean not :true the symbol !
这篇关于:多态/:通过ActiveRecord关联(Rails的3.2)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!