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

Valentin Vasilyev
quelle
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 .

Ryan Bigg
quelle
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
8

Beachten Sie, dass dies in der API behandelt wird.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_and_belongs_to_many

Sai Perchard
quelle
1
Obwohl es irgendwo in einem Leitfaden erwähnt werden sollte.
Sholsinger
Lesen Sie diese wenigen Zeilen in der API, damit Sie den erwarteten Namen der Tabelle verstehen (z. B. wenn Sie dasselbe Präfix verwenden). Dies erklärt den Kommentar von @Giovanni.
Hugo Logmans
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.

Jack Chu
quelle
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
1

In Kombination mit dieser Frage (1. Antwort) Wie man von hier aus eine typische HABTM-Rollenbeziehung für Benutzer und eine erste Antwort erstellt, muss dies auch von einem Affen verstanden werden. Ich bin neu in RoR und es funktioniert wie ein Zauber

mArtinko5MB
quelle