2009-02-19 11 views
77

Je me bats maintenant pour que HATBM fonctionne correctement. J'ai un scanario battu: articles et tags. Je suppose, HABTM devrait être utilisé ici, car il s'agit d'une relation plusieurs-à-plusieurs. Je ne sais pas cependant si je devrais créer manuellement une table de jointure (articles_tags dans ce cas).Ai-je besoin de créer manuellement une migration pour une table de jointure HABTM?

Mon code actuellement comme suit:

class Article < ActiveRecord::Base 
    has_and_belongs_to_many :tags 
end 

class Tag < ActiveRecord::Base 
    has_and_belongs_to_many :articles 
end 

Quand je lance les migrations, aucune 3ème table est créée. En outre, je voudrais ajouter que ma troisième table ne porte aucune logique de domaine, juste l'assignation aveugle.

J'utilise Rails 2.2.2

+1

Même aux rails 4, je devine la réponse à ceci est ... "oui"? :( – dtc

+1

@dtc, toujours oui, toujours vrai – Valentin

Répondre

140

Vous devriez faire ceci dans une migration de l'une des tables, ou dans une migration séparée si ces migrations ont été RAN:

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

add_index :articles_tags, [:article_id, :tag_id] 

Cette volonté créez la table pour vous et le :id => false dit à Rails de ne pas ajouter un champ d'identification à cette table. Il y a aussi un index, qui va accélérer les recherches pour cette table de jointure.

Vous pouvez également générer un modèle (ArticlesTag) pour cela et faire:

# 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 

Et puis créer la table dans la migration générée par l'appel script/generate model articles_tag.

+0

Merci, Radar, c'est ce dont j'avais besoin! – Valentin

+12

Drôle que les guides officiels ou la documentation ne l'indique pas .J'ai dû creuser sur Stackoverflow. – lzap

+0

Et si vous vouliez les associer avec un nom unique pour la jointure, car cette jointure était déjà utilisée. – Trip

7

Vous voulez probablement aussi d'ajouter un index à la migration:

add_index "articles_tags", "article_id"

add_index "articles_tags", "tag_id"

Cependant, si vous voulez le marquage fonctionnalité que je vous recommande le plugin rails acts_as_taggable_on:

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

Je l'ai utilisé sur un projet et il était très facile à implémenter. L'un des problèmes avec une table de jointure pour le balisage est qu'elle peut facilement devenir moche en créant une table de jointure pour chaque type de contenu que vous souhaitez faire taggable (c'est-à-dire comments_tags, posts_tags, images_tags, etc.). Ce plugin utilise une table de taggings qui inclut un discriminateur pour déterminer le type de contenu sans avoir besoin d'une table de jointure spécifique pour chaque type.

+0

Les références de méthodes de migration (ou belongs_to) ajoutent automatiquement des index. Tu n'as pas besoin de ça. Vous pouvez casser votre migration avec elle. – lzap

+0

Les références de méthodes de migration (ou belongs_to) n'ajoutent pas automatiquement d'index. (Pensé qu'ils font :-) – lzap

+0

À mon humble avis, il serait préférable de créer une clé primaire composite. Mais c'est spécifique à la base de données. –

Questions connexes