1

Dans Rails - quel est l'effet de l'utilisation has_many: à travers avec has_and_belongs_to_many? Envisager d'avoir deux modèles - comme indiqué ci-dessous et les balises qui messages ont plusieurs-à-plusieurs:has_many: à travers avec has_and_belongs_to_many dans Rails

class Tag < ActiveRecord::Base 
    has_many :posts_tag 
    has_and_belongs_to_many :posts 
end 

class Post < ActiveRecord::Base 
    has_many :posts_tag 
    has_many :tags, :through => posts_tag 
end 

class PostsTag < ActiveRecord::Base 
    belongs_to :tag 
    belongs_to :post 
end 

La raison pour laquelle j'utilise has_and_belongs_to_many est parce qu'un tag appartient à de nombreux postes.

J'ai regardé dans le Rails Association guide et de voir qu'ils ne mentionnent pas ce cas pour une relation many-to-many. J'ai, cependant, essayé ceci et l'exécutant dans Rails n'a donné aucun comportement et de la petite base de données de test que j'ai construite, a également semblé renvoyer les résultats corrects pour post.tags et tag.posts - où post et tag se rapportent à une instance du Modèles Post et Tag respectivement.

Est-ce que c'est l'utilisation correcte ou est-ce que j'ai des effets secondaires dont je ne suis pas au courant? Aussi, si c'est correct, est-ce la façon Rails d'y parvenir?

Merci!

Répondre

2

Vous utilisez has_and_belongs_to_many uniquement lorsque vous définissez une association plusieurs-à-plusieurs (en d'autres termes, lorsque l'autre côté a également has_and_belongs_to_many). C'est le sens de cette association.

Vous devriez avoir

class Tag < ActiveRecord::Base 
    has_many :posts_tags 
    has_many :posts, :through => :post_tags 
end 

class PostsTag < ActiveRecord::Base 
    belongs_to :tag 
    belongs_to :post 
end 

class Post < ActiveRecord::Base 
    has_many :posts_tags 
    has_many :tags, :through => :posts_tags 
end 

Notez que j'ai utilisé le pluriel, post_tags (parce que c'est la bonne façon).

Si vous avez la situation comme dans votre commentaire, vous devez avoir un

belongs_to :post_tag 

dans votre modèle Post et

has_many :posts 

dans votre modèle PostTag.

Vous pouvez maintenant demander: « Pourquoi devrais-je utiliser belongs_to :post_tag Il n'a pas appartiennent à une balise, il a une étiquette Donc, je ne devrais pas utiliser has_one :post_tag?.? ». C'était aussi ma question au début, mais je me suis dit que Rails ne peut pas toujours parfaitement convenir à la langue anglaise. Vous avez besoin de la colonne post_tag_id sur votre post, et belongs_to s'attend exactement à cela. D'autre part, has_one s'attendrait à ce qu'une colonne nommée post_id soit présente sur le côté autre côté, c'est-à-dire dans votre post_tag. Mais ce serait impossible, car post_tag a beaucoup posts (pas seulement un), de sorte que les ID post ne peuvent pas être conservés dans post_tags.

Mise à jour:
La différence entre les associations ne sont que dans les méthodes qui vous sont fournies et les options que vous pouvez transmettre (celui expliqué dans les rails de guidage sur les associations). Par exemple, has_one et belongs_to ont les mêmes méthodes:

association(force_reload = false) 
association=(associate) 
build_association(attributes = {}) 
create_association(attributes = {}) 

Mais, par exemple, les méthodes et association=create_association impliquent des choses différentes concernant où devrait être (comme je l'ai expliqué ci-dessus) la clé étrangère.

has_and_belongs_to_many et has_many probablement n'ont rien de différent dans leurs méthodes, mais ils diffèrent dans les options que vous pouvez passer. Par exemple, vous pouvez passer

:dependent => :destroy 

sur l'association has_many, mais vous ne pouvez pas passer à un has_and_belongs_to_many, parce que cela n'a pas de sens, car il implique un grand nombre à many; Si un enregistrement parent est détruit, les enregistrements enfants peuvent toujours être connectés à d'autres enregistrements, ils ne doivent donc pas être détruits.

+0

Oui, je pense que la partie où vous avez dit "Rails ne peut pas toujours correspondre parfaitement à la langue anglaise" est ce que je recherchais vraiment: P Étant donné que certaines opérations communes fonctionnaient avec un 'has_many: through' et' has_and_belongs_to_many', D'un point de vue purement pédagogique, il serait intéressant de savoir si cela a des effets secondaires. Je comprends que ce n'est pas la bonne façon de l'utiliser. –

+0

Regardez la mise à jour. –

+0

Merci! Ça a du sens :) –

1

Bien que je ne suis pas sûr des effets exacts d'avoir une has_many :through d'un côté d'une relation et un has_and_belongs_to_many de l'autre côté, je ne sais que la façon plus correcte, serait d'utiliser une has_many :through inversée comme si :

class Tag < ActiveRecord::Base 
    has_many :posts_tag 
    has_many :posts, :through => posts_tag 
end 

Garder les autres relations identiques.

+0

Que diriez-vous des effets secondaires de l'utilisation de 'has_one' d'un côté d'une relation et' has_and_belongs_to_many' de l'autre côté? Par exemple dans les exemples ci-dessus, si nous disions que chaque 'post' peut avoir au plus un' tag'. Cependant, un 'tag' appartiendrait à beaucoup de' posts'. –

+0

Dans ce cas, vous avez la relation un peu en arrière. Tag 'has_many' Posts, et Posts' belongs_to' un Tag. Post aurait tag_id, ne permettant qu'un seul tag. 'has_and_belongs_to_many' va utiliser une table de jointure cachée que' has_many' n'utilisera pas. – ctcherry

Questions connexes