6

Mój schemat mai Journals, które można oznaczyć za pomocą Tags. Wymaga to skojarzenia has_many through: z polimorficzną relacją do mojej tabeli łączenia Tagging.Model szyn z dwoma polimorficznymi has_many through: powiązania dla tagowania obiektów

Okay, to łatwa i dobrze udokumentowana część.

Mój problem polega na tym, że Articles może zawierać zarówno znaczniki podstawowe, jak i podw tagi. Główne elementy są tym, co mnie najbardziej interesuje, ale mój model musi również śledzić te znaczniki podrzędne. Tagi podrzędne to po prostu etykiety opisujące Article, które mają mniejsze znaczenie, ale pochodzą z tej samej globalnej puli Tags. (w rzeczywistości jeden znacznik podstawowy Article może być pod-znacznikiem innego).

Osiągnięcie tego celu wymaga modelu Article mieć dwa stowarzyszenia do modelu Tagging i dwa has_many through: stowarzyszeniom Tags (tj #tags & # sub-tags)

To, co mam tak daleko, co robi, gdy ważna nie zachowują oddzielnych znaczników i podtasów podrzędnych.

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 

wiem, że gdzieś tam muszę znaleźć właściwą kombinację source i source_type ale nie mogę się dogadać.

Dla kompletności tutaj jest mój article_spec.rb, którego używam do testowania tego - obecnie nie działa w "błędnych tagach".

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 

Z góry dziękuję za pomoc w osiągnięciu tego. Głównym problemem jest to, że nie mogę się dowiedzieć, jak powiedzieć Railsowi typ_źródła, który będzie używany dla powiązań sub_tags w artykułach.

Odpowiedz

10

Hmmm ... Cisza znowu ...? Co daje SO? Cześć...? Bueller?

Nie bój się, oto odpowiedź:

Po patrząc Single Table Inheritance (nie odpowiedź, ale interesująca technika dla innych nieco związanych z problemami), natknąłem SO pytanie dotyczące wielu odniesień do polimorficznego skojarzenia w tym samym modelu. (Dziękuję Hakunin Dla Państwa detailed answer, +1).

Zasadniczo musimy wyraźnie określić zawartość kolumny taggable_type w tabeli Taggings dla stowarzyszenia sub_taggings, ale nie z source lub source_type, zamiast z :conditions.

Article modelu poniżej przepływa wszystkie testy:

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:

to prawidłowe Tag model, który tworzy funkcjonalne odwrotnych polimorficzne związki tagów. Odwrotne powiązanie (tj. Tag.articles i Tag.sub_tagged_articles) przechodzi testy.

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 

Mam również rozszerzony i pomyślnie przetestowany schemat, aby umożliwić tagging & sub_tagging innych modeli wykorzystujących ten sam model Tag i tagowanie dołączyć tabelę. Mam nadzieję, że to pomaga komuś.