我有一个标签系统,可以适用于各种Taggable
s。我希望能够透明地查询它们,就像这里接受的解决方案一样:
例如,我希望能够告诉我所有标记为“foo”的Post
s、Page
s、Video
s 等。相当直截了当。并发症:
- 不同种类的
Taggable
s 在 OO 意义上不是多态的,只是通过多态关联。有一张表可以保证 taggable_id (中的主键等)的唯一性。taggables
posts
Tag
毫不奇怪,s 与 s 具有多对多关系Taggable
,并且通过map_tags
表关联。
楷模:
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
问题:
- 我想我的第一个问题应该是:这甚至可能吗?我已经看到模型“具有许多”多态关联实例,但我不确定它是否以其他方式工作,因为下面的错误消息可能暗示......
- 我是否正确设置了多态性?我的理解是,“子”模型基本上将自己声明为“标记”,并且直接与它们交互的表(在这种情况下
map_tags
)是获得:polymorphic
声明的表。 - 如何在 ActiveRecord-speak 中说“给我展示所有标有 'foo' 的东西”?
我试过的:
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'.
...
编辑
我找到了这篇文章,其中指出我需要指定:source
and :source_type
。所以:
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
我想我更接近(?),但我仍然不确定如何查询关联的对象......
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'.