Rails模型具有两个多态的has_many through:对象标记关联



我的模式有可以用Tags标记的ArticlesJournals。这需要一个与我的Tagging联接表具有多态关系的has_many through:关联。

好吧,这就是简单且有充分记录的部分。

我的问题是Articles可以同时具有主标签和子标签。主要标签是我最感兴趣的,但我的模型也需要跟踪这些子标签。子标签只是描述Article的标签,其重要性较低,但来自Tags的同一全局池。(实际上,一个Article的主标签可能是另一个的子标签(。

实现这一点需要Article模型具有到Tagging模型的两个关联和到Tags的两个has_many through:关联(即#tags和#sub-tag(

到目前为止,这就是我所拥有的,虽然有效,但并没有将主标签和子标签分开。

class Article < ActiveRecord::Base
  has_many :taggings, as: :taggable
  has_many :tags, through: :taggings
  has_many :sub_taggings, as: :taggable, class_name: 'Tagging',
           source_type: 'article_sub'
  has_many :sub_tags, through: :sub_taggings, class_name: 'Tag', source: :tag
end
class Tagging < ActiveRecord::Base
  #  id            :integer
  #  taggable_id   :integer
  #  taggable_type :string(255)
  #  tag_id        :integer
  belongs_to :tag
  belongs_to :taggable, :polymorphic => true
end
class Tag < ActiveRecord::Base
  has_many :taggings
end

我知道在那里的某个地方我需要找到sourcesource_type的正确组合,但我无法找到。

为了完整起见,这里是我的article_spec.rb,我正在使用它来测试这一点——目前在"不正确的标签"上失败了。

describe "referencing tags" do
  before do
    @article.tags << Tag.find_or_create_by_name("test")
    @article.tags << Tag.find_or_create_by_name("abd")
    @article.sub_tags << Tag.find_or_create_by_name("test2")
    @article.sub_tags << Tag.find_or_create_by_name("abd")
  end
  describe "the correct tags" do
    its(:tags) { should include Tag.find_by_name("test") }
    its(:tags) { should include Tag.find_by_name("abd") }
    its(:sub_tags) { should include Tag.find_by_name("abd") }
    its(:sub_tags) { should include Tag.find_by_name("test2") }
  end
  describe "the incorrect tags" do
    its(:tags) { should_not include Tag.find_by_name("test2") }
    its(:sub_tags) { should_not include Tag.find_by_name("test") }
  end
end

提前感谢您为实现这一目标提供的任何帮助。主要的问题是我不知道如何告诉Rails文章中sub_tags关联要使用的source_type。

嗯。。。再次沉默。。。?SO是什么?你好布勒?

永远不要害怕,答案如下:

在研究了单表继承(不是答案,但对于其他稍微相关的问题,这是一种有趣的技术(之后,我偶然发现了一个SO问题,该问题涉及对同一模型上多态关联的多个引用。(感谢hakunin的详细回答,+1。(

基本上,我们需要为sub_taggings关联显式定义Taggings表中taggable_type列的内容,但不使用sourcesource_type,而是使用:conditions

下面显示的Article模型现在通过了所有测试:

 class Article < ActiveRecord::Base
   has_many :taggings, as: :taggable
   has_many :tags, through: :taggings, uniq: true, dependent: :destroy
   has_many :sub_taggings, as: :taggable, class_name: 'Tagging',
             conditions: {taggable_type: 'article_sub_tag'},
             dependent: :destroy
   has_many :sub_tags, through: :sub_taggings, class_name: 'Tag',
             source: :tag, uniq: true
 end

更新:

这是在标签上产生功能性反向多态性关联的正确Tag模型。反向关联(即Tag.articles和Tag.sub_tagged_articles(通过测试。

 class Tag < ActiveRecord::Base
   has_many :articles, through: :taggings, source: :taggable,
             source_type: "Article"
   has_many :sub_tagged_articles, through: :taggings, source: :taggable,
             source_type: "Article_sub_tag", class_name: "Article"
 end

我还扩展并成功地测试了该模式,以允许标记&使用相同Tag模型和tagging联接表的其他模型的sub_tagging。希望这能帮助到别人。

最新更新