Muss ich manuell eine Migration für eine HABTM-Join-Tabelle erstellen?


77

Ich kämpfe jetzt darum, dass HATBM richtig funktioniert. Ich habe ein geschlagenes Scanario: Artikel und Tags. Ich nehme an, HABTM sollte hier verwendet werden, da es sich um eine Viele-zu-Viele-Beziehung handelt. Ich weiß jedoch nicht, ob ich manuell eine Join-Tabelle erstellen soll (in diesem Fall articles_tags).

Mein Code lautet derzeit wie folgt:

class Article < ActiveRecord::Base
  has_and_belongs_to_many :tags  
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :articles
end

Wenn ich die Migrationen ausführe, wird keine dritte Tabelle erstellt. Außerdem möchte ich hinzufügen, dass meine dritte Tabelle keine Domänenlogik enthält, sondern nur eine blinde Zuweisung.

Ich benutze Rails 2.2.2


1
Selbst bei Schienen 4 ist die Antwort darauf wohl ... "Ja"? :(
dtc

1
@dtc, immer noch ja, immer noch wahr.
Valentin Vasilyev

Antworten:


141

Sie sollten dies bei einer Migration einer der Tabellen oder bei einer separaten Migration tun, wenn diese Migrationen ausgeführt wurden:

create_table :articles_tags, :id => false do |t|
  t.references :article, :tag
end

add_index :articles_tags, [:article_id, :tag_id]

Dadurch wird die Tabelle für Sie erstellt und :id => falseRails wird angewiesen, dieser Tabelle kein ID-Feld hinzuzufügen. Es gibt auch einen Index, der die Suche nach dieser Join-Tabelle beschleunigt.

Sie können auch ein Modell (ArticlesTag) dafür generieren und Folgendes tun:

# article.rb
has_many :articles_tags
has_many :tags, :through => :articles_tags

# tag.rb
has_many :articles_tags
has_many :articles, :through => :articles_tags

# article_tag.rb
belongs_to :tag
belongs_to :article

Erstellen Sie dann die Tabelle in der Migration, die aus dem script/generate model articles_tagAufruf generiert wurde .


Danke, Radar, das habe ich gebraucht!
Valentin Vasilyev

12
Komisch, dass offizielle Anleitungen oder Dokumentationen dies nicht angeben. Ich musste auf Stackoverflow graben. Ty.
lzap

Was wäre, wenn Sie sie mit einem eindeutigen Namen für den Join verknüpfen möchten, da dieser Join bereits verwendet wurde?
Reise

Ich denke, Sie sollten Indizes hinzufügen, um Tabelle zu verbinden, indem Sie add_index :articles_tags, [:article_id, :tag_id]vor dem Ende der changeMethode hinzufügen
Giovanni Cappellotto

@ Giovanni: Fertig. Vielen Dank!
Ryan Bigg


7

Sie möchten der Migration wahrscheinlich auch einen Index hinzufügen:

add_index "articles_tags", "article_id"

add_index "articles_tags", "tag_id"

Wenn Sie jedoch Tagging-Funktionen wünschen, würde ich das Acts_as_taggable_on Rails-Plugin empfehlen:

http://www.intridea.com/tag/acts_as_taggable_on http://github.com/mbleigh/acts-as-taggable-on/

Ich habe es für ein Projekt verwendet und es war sehr einfach zu implementieren.

Eines der Probleme mit einer Verknüpfungstabelle zum Markieren besteht darin, dass das Erstellen einer Verknüpfungstabelle für jeden Inhaltstyp, den Sie taggbar machen möchten (z. B. Kommentare_Tags, Posts_Tags, Bilder_Tags usw.), leicht hässlich werden kann. Dieses Plugin verwendet eine Taggings-Tabelle, die einen Diskriminator enthält, um den Inhaltstyp zu bestimmen, ohne dass für jeden Typ eine bestimmte Join-Tabelle erforderlich ist.


Migrationsmethodenreferenzen (oder Gehört zu) fügen automatisch Indizes hinzu. Das brauchst du nicht. Sie können Ihre Migration damit unterbrechen.
lzap

Migrationsmethodenreferenzen (oder Gehört zu) fügen nicht automatisch Indizes hinzu. (
Dachten

IMHO wäre es besser, einen zusammengesetzten Primärschlüssel zu erstellen. Aber es ist datenbankspezifisch.
Art Shayderov

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.