36 votes

La configuration d'un polymorphe has_many :la relation d'aide

rails g model Article name:string
rails g model Category name:string
rails g model Tag name:string taggable_id:integer taggable_type:string category_id:integer

J'ai créé mes modèles, comme indiqué dans le code précédent. Les Articles seront l'un des nombreux modèles qui peuvent avoir des balises. La catégorie modèle contiendra toutes les catégories qui peuvent lui être confiées. La balise modèle sera un polymorphe à la jointure de table qui représente tagged relations.

class Article < ActiveRecord::Base
  has_many :tags, :as => :taggable
  has_many :categories, :through => :taggable
end

class Category < ActiveRecord::Base
  has_many :tags, :as => :taggable
  has_many :articles, :through => :taggable
end

class Tag < ActiveRecord::Base
  belongs_to :taggable, :polymorphic => true
  belongs_to :category
end

Je n'arrive pas à obtenir que cela fonctionne, je peux le faire non polymorphes, mais je dois avoir quelque chose de mal avec le polymorphe de la partie. Des idées?

Edit: Toujours pas à obtenir ce droit:

class Article < ActiveRecord::Base
    has_many :taggables, :as => :tag
    has_many :categories, :through => :taggables, :source => :tag, :source_type => "Article"
end
class Category < ActiveRecord::Base
    has_many :taggables, :as => :tag
    has_many :articles, :through => :taggables, :source => :tag, :source_type => "Article"
end
class Tag < ActiveRecord::Base
  belongs_to :taggable, :polymorphic => true
  belongs_to :category
end

88voto

Serodis Points 1104

Pour créer un polymorphe has_many :through, vous devez d'abord créer vos modèles. Nous allons utiliser Article,' "Catégorie" et " Tag " où " Tag " est la jointure de modèle et de l'Article est l'un des nombreux objets qui peuvent être "marqué" avec une catégorie.

Tout d'abord vous créer votre "Article" et "Catégorie" modèles de. Ce sont des modèles de base qui n'ont pas besoin d'une attention particulière, tout de suite:

rails g model Article name:string
rails g model Category name:string

Maintenant, nous allons créer notre polymorphe à la jointure de la table:

rails g model Tag taggable_id:integer taggable_type:string category_id:integer

La jointure de table réunit deux tables, ou dans notre cas, une table à beaucoup d'autres personnes via le comportement polymorphique. Il le fait par le stockage de l'ID à partir de deux tableaux distincts. Cela crée un lien. Notre "Catégorie" tableau sera toujours une "Catégorie", afin d'inclure 'category_id.' Les tables liens de varier, donc nous ajoutons un élément 'taggable_id' qui contient l'id de tout tagable élément. Ensuite, nous utilisons des "taggable_type' pour terminer le lien permettant le lien pour savoir ce que c'est lié, comme par exemple un article.

Maintenant, nous devons mettre en place nos modèles:

class Article < ActiveRecord::Base
  has_many :tags, :as => :taggable, :dependent => :destroy
  has_many :categories, :through => :tags
end
class Category < ActiveRecord::Base
  has_many :tags, :dependent => :destroy
  has_many :articles, :through => :tags, :source => :taggable, :source_type => 'Article'
end
class Tag < ActiveRecord::Base
  belongs_to :taggable, :polymorphic => true
  belongs_to :category
end

Après cela, la configuration de votre base de données à l'aide de:

rake db:migrate

Ça y est! Maintenant, vous pouvez configurer votre base de données avec des données réelles:

Category.create :name => "Food"
Article.create :name => "Picking the right restaurant."
Article.create :name => "The perfect cherry pie!"
Article.create :name => "Foods to avoid when in a hurry!"
Category.create :name => "Kitchen"
Article.create :name => "The buyers guide to great refrigeration units."
Article.create :name => "The best stove for your money."
Category.create :name => "Beverages"
Article.create :name => "How to: Make your own soda."
Article.create :name => "How to: Fermenting fruit."

Maintenant, vous avez un peu de catégories et d'articles divers. Ils ne sont pas classés à l'aide de balises, cependant. Donc, nous avons besoin de le faire:

a = Tag.new
a.taggable = Article.find_by_name("Picking the right restaurant.")
a.category = Category.find_by_name("Food")
a.save

Vous pouvez ensuite répéter cette opération pour chacun, cela permettra de relier vos catégories et articles. Après avoir fait cela, vous serez en mesure d'accéder à chaque article les catégories et chaque catégorie d'articles:

Article.first.categories
Category.first.articles

Notes:

1)Chaque fois que vous voulez supprimer un élément qui est lié par un lien-modèle assurez-vous d'utiliser les détruire." Lorsque vous détruisez un objet lié, il permettra également de détruire le lien. Cela garantit qu'il n'y a pas de mauvais ou de liens morts. C'est pourquoi nous utilisons ':fonction => :détruire'

2)Lors de la mise en place de notre "Article" le modèle, qui est l'un de nos " tagable modèles, il doit être lié à l'aide :comme. Car dans l'exemple précédent, nous avons utilisé des taggable_type " et "taggable_id' que nous utilisons :sous => :tagable. Cela permet de rails pour savoir comment stocker les valeurs dans la base de données.

3)Lors de la liaison des catégories d'articles, nous utilisons: has_many :articles, :par => :balises :source => :tagable, :source_type => 'Article' Ceci indique la catégorie de modèle qu'il faut avoir beaucoup de :articles à travers :les tags. La source est :tagable, pour la même raison que ci-dessus. La source est de type "Article", car un modèle pour définir automatiquement taggable_type à son propre nom.

15voto

Gerry Points 2919

Vous ne peut tout simplement pas faire la table de jointure polymorphe, au moins Rails ne prend pas en charge cette sortie de la boîte. La solution est (prises à partir d'Obie Rails 3 voies):

Si vous en avez vraiment besoin, has_many :through est possible avec polymorphes associations, mais seulement en spécifiant exactement quel type polymorphe associations que vous voulez. Pour ce faire, vous devez utiliser l' :source_type option. Dans la plupart des cas, vous devrez utiliser l' :source option, car l'association nom ne correspond pas au nom de l'interface utilisée pour le polymorphe de l'association:

class User < ActiveRecord::Base
  has_many :comments
  has_many :commented_timesheets, :through => :comments, :source => :commentable,
           :source_type => "Timesheet"
  has_many :commented_billable_weeks, :through => :comments, :source => :commentable,
           :source_type => "BillableWeek"

C'est détaillé et le projet dans son ensemble perd de son élégance si vous aller dans cette voie, mais il fonctionne:

User.first.commented_timesheets

J'espère que j'ai aidé!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X