2011-05-04 22 views
35
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 

He creado mis modelos como se muestra en el código anterior. Los artículos serán uno de muchos modelos que pueden tener etiquetas. El modelo de categoría contendrá todas las categorías que pueden asignarse. El modelo de etiqueta será una tabla de unión polimórfica que representa las relaciones etiquetadas.Configurando un polimorfo has_many: a través de la relación

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 

Me parece que no puede conseguir que esto funcione, yo puedo hacerlo no polimórfica, pero debo tener algo malo en la parte polimórfica. ¿Algunas ideas?

Editar: Todavía no conseguir este derecho:

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 
+1

Voy a tratar de probar esto un poco hoy para ver si entiendo completamente cómo hacerlo. – Serodis

Respuesta

87

Para crear un hashman multimórfico: a través, primero debe crear sus modelos. Usaremos 'Artículo', '' Categoría 'y' Etiqueta ', donde' Etiqueta 'es el modelo de unión y Artículo es uno de muchos objetos que pueden ser' etiquetados 'con una categoría.

Primero crea sus modelos 'Artículo' y 'Categoría'. Estos son los modelos básicos que no necesitan ninguna atención especial, por el momento:

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

Ahora, vamos a crear nuestra polimórfica unirse a la mesa:

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

El-tabla de unión une dos tablas, o en nuestro caso una tabla a muchas otras a través de un comportamiento polimórfico. Lo hace almacenando la ID de dos tablas separadas. Esto crea un enlace. Nuestra tabla de 'Categoría' siempre será una 'Categoría' por lo que incluimos 'category_id'. Las tablas a las que se vincula varían, por lo que agregamos un elemento 'taggable_id' que contiene la identificación de cualquier elemento etiquetable. Luego, usamos 'taggable_type' para completar el enlace, lo que permite que el enlace sepa a qué está vinculado, como un artículo.

Ahora, tenemos que configurar nuestros modelos:

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 

Después de esto, la configuración de la base de datos mediante:

rake db:migrate 

eso es todo!Ahora, puede configurar su base de datos con datos reales:

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." 

Ahora usted tiene algunas categorías y varios artículos. Sin embargo, no están categorizados usando etiquetas. Entonces, tendremos que hacer eso:

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

Luego puede repetir esto para cada uno, esto enlazará sus categorías y artículos. Después de hacer esto usted será capaz de acceder a las categorías de cada artículo y los artículos de cada Categoría del alojamiento:

Article.first.categories 
Category.first.articles 

Notas:

1) Cada vez que desee eliminar un elemento que está unida por un enlace de modelo asegúrese de usa "destruir". Cuando destruyes un objeto vinculado, también destruirá el enlace. Esto asegura que no hay enlaces malos o muertos. Es por eso que usamos ': dependent =>: destroy'

2) Al configurar nuestro modelo 'Artículo', que es uno de nuestros modelos 'etiquetables', se debe vincular usando: as. Como en el ejemplo anterior usamos 'taggable_type' y 'taggable_id' utilizamos: as =>: taggable. Esto ayuda a los rieles a saber cómo almacenar los valores en la base de datos.

3) Cuando la vinculación de categorías a los artículos, utilizamos: has_many: artículos,: a través de =>: etiquetas,: fuente =>: taggable,: source_type => 'Artículo' Esto le dice al modelo de la categoría que debería tener muchos: artículos a través de: etiquetas. La fuente es: etiquetable, por la misma razón que la anterior. El tipo de fuente es "Artículo" porque un modelo establecerá automáticamente taggable_type a su propio nombre.

+2

¿Puede incluir los índices óptimos en la migración? – ajbraus

+0

¿Cómo funcionaría la vista para esto? Puedo hacer que se renderice, pero no para guardar en la base de datos. Intenté: '<% = f.collection_select: tags, Category.all,: id,: name, {: prompt => 'Seleccionar hasta 3'}, {: clase => 'o-input - quiet '}%> ' – Erica

14

Simplemente no se puede hacer la tabla de unión polimórfica, al menos rieles no admite esta fuera de la caja. La solución es (tomado de manera Rails 3 de Obie):

Si realmente lo necesita, has_many :through es posible con asociaciones polimórficas, pero sólo especificando exactamente qué tipo de asociaciones polimórficas desea. Para hacerlo, debe usar la opción :source_type. En la mayoría de los casos, tendrá que utilizar la opción :source, ya que el nombre de la asociación no coincidirá con el nombre de la interfaz utilizada para la asociación polimórfica:

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" 

Es prolijo y todo el esquema pierde su elegancia si seguir este camino, pero funciona:

User.first.commented_timesheets 

Espero ayudado!

+0

He actualizado, todavía un poco confundido en toda esta configuración. – Serodis

+0

hizo mi día !!!! –

Cuestiones relacionadas