6

Mein Schema hat Articles und Journals, die mit Tags getaggt werden können. Dies erfordert eine has_many through: Assoziation mit einer polymorphen Beziehung zu meiner Tagging Join-Tabelle.Schienenmodell mit zwei polymorphen has_many bis: Assoziationen für die Objektkennzeichnung

Okay, das ist der einfache und gut dokumentierte Teil.

Mein Problem ist, dass Articles sowohl primäre Tags als auch Unter-Tags haben kann. Die primären Tags sind das, was mich am meisten interessiert, aber mein Modell muss auch diese Sub-Tags verfolgen. Unter-Tags sind einfach Labels, die die Article beschreiben, die von geringerer Wichtigkeit sind, aber aus demselben globalen Pool von Tags stammen. (In der Tat, ein primary-Tag eines Article kann das Sub-Tag eines anderen sein).

Die Verwirklichung dieses Ziels erfordert die Article Modell zwei Assoziationen zum Tagging Modell zu haben und zwei has_many through: Assoziationen Tags (dh #tags & # sub-Tags)

Das ist, was ich bisher habe, die während gültig tut Primär-Tags und Unter-Tags nicht getrennt halten.

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 

Ich weiß, irgendwo, dass es in ich die richtige Kombination von source und source_type finden müssen, aber ich kann es nicht funktioniert.

Der Vollständigkeit halber ist meine article_spec.rb, die ich benutze, um dies zu testen - derzeit auf "die falschen Tags" scheitern.

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 

Vielen Dank im Voraus für jede Hilfe bei der Erreichung dieser. Das Hauptproblem ist, dass ich nicht herausfinden kann, wie ich Rails den source_type mitteilen kann, der für die sub_tags association in Articles verwendet werden soll.

Antwort

10

Hmmm ... Stille wieder ...? Was gibt SO? Hallo...? Bueller?

Keine Angst, hier ist die Antwort:

Nach einem Blick in Single Table Inheritance (nicht die Antwort, aber eine interessante Technik für andere leicht bedingte Probleme), stolperte ich über eine SO Frage in Bezug auf mehrere Verweise zu einer polymorphen Assoziation am selben Modell. (Vielen Dank für Ihre Hakunin detailed answer, +1.)

Grundsätzlich müssen wir den Inhalt der taggable_type Spalte in der Taggings Tabelle für die sub_taggings Vereinigung explizit definieren, aber nicht mit source oder source_type, statt mit :conditions.

Das Article Modell unten nun gezeigt, geht alle Tests:

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 

UPDATE:

Dies ist das richtige Tag Modell, die funktionellen Reverse polymorphe Assoziationen auf Tags erzeugt. Die umgekehrte Assoziation (dh Tag-Artikel und Tag-Tag-Artikel) besteht Tests.

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 

Ich habe auch erweitert und erfolgreich getestet, das Schema & sub_tagging von anderen Modellen zu ermöglichen Tagging den gleichen Tag-Modell und Tagging Tisch sitzen. Hoffe, das hilft jemandem.

Verwandte Themen