2009-01-06 12 views
22

Otra cuestión básica Rieles:Andamio ActiveRecord: dos columnas del mismo tipo de datos

Tengo una tabla de base de datos que debe contener referencias a exactamente dos diferentes registros de un tipo de datos específico.

Ejemplo hipotético: Estoy creando una base de datos de videojuegos. Tengo una tabla para "Empresas". Quiero tener exactamente un desarrollador y exactamente un editor para cada entrada de "Videojuego".

Sé que si quiero tener una empresa, que sólo puede hacer algo como:

script/generate Videogame company:references 

Pero tengo que tener ambas compañías. Prefiero no usar una tabla de unión, ya que solo puede haber exactamente dos del tipo de datos dado, y los necesito para que sean distintos.

Parece que la respuesta debería ser bastante obvia, pero no puedo encontrarla en ningún lado en Internet.

Respuesta

45

Sólo para cosas ordenado un poco, en su migración ahora también puede hacer:

create_table :videogames do |t| 
    t.belongs_to :developer 
    t.belongs_to :publisher 
end 

Y puesto que está llamando las teclas developer_id y PUBLISHER_ID, el modelo probablemente debería ser:

belongs_to :developer, :class_name => "Company" 
belongs_to :publisher, :class_name => "Company" 

No es un problema importante, pero me parece que a medida que se agrega el número de asociaciones con argumentos adicionales, las cosas menos claras se vuelven, por lo que es mejor mantener los valores predeterminados siempre que sea posible.

+0

Intenté esto y ahora tengo developer_id pero no puedo acceder a game.developer. Tengo en mi clase de videojuegos attr_accessible: developer. – quantumpotato

+0

Probablemente esto ya se haya resuelto, pero ¿has agregado has_many: juegos (o algo así) a tu modelo de desarrollador? – MrWater

+0

¿Cómo hago las asignaciones inversas? –

9

No tengo idea de cómo hacer esto con script/generate.

La idea subyacente es más fácil de mostrar sin usar script/generate de todos modos. Desea dos campos en su tabla/modelo de videojuegos que contengan las claves externas a la tabla/modelo de empresas.

Le mostraré lo que creo que se parecería al código, pero no lo he probado, así que podría estar equivocado.

Su archivo de migración tiene:

create_table :videogames do |t| 
    # all your other fields 
    t.int :developer_id 
    t.int :publisher_id 
end 

Luego, en su modelo:

belongs_to :developer, class_name: "Company", foreign_key: "developer_id" 
belongs_to :publisher, class_name: "Company", foreign_key: "publisher_id" 

También menciona querer las dos empresas a ser distinto, que se podía manejar en una validación en el modelo que comprueba que developer_id != publisher_id.

+0

Como nota al margen, el parámetro foreign_key aquí no es necesario, ya que el nombre predeterminado es la asociación + "_id". Para obtener más información, consulte http://www.spacevatican.org/2008/5/6/creating-multiple-associations-with-the-same-table/ –

2

Si hay algún método o validación que desee específico para un determinado tipo de empresa, puede clasificar el modelo de la empresa. Esto emplea una técnica llamada herencia de tabla única. Para obtener más información echa un vistazo a este artículo: http://wiki.rubyonrails.org/rails/pages/singletableinheritance

A continuación, tendría:

#db/migrate/###_create_companies 
class CreateCompanies < ActiveRecord::Migration 
    def self.up 
    create_table :companies do |t| 
     t.string :type # required so rails know what type of company a record is 
     t.timestamps 
    end 
    end 

    def self.down 
    drop_table :companies 
    end 
end 

#db/migrate/###_create_videogames 
class CreateVideogames < ActiveRecord::Migration 
    create_table :videogames do |t| 
    t.belongs_to :developer 
    t.belongs_to :publisher 
    end  

    def self.down 
    drop_table :videogames 
    end 
end 

#app/models/company.rb 
class Company < ActiveRecord::Base 
    has_many :videogames 
    common validations and methods 
end 

#app/models/developer.rb 
class Developer < Company 
    developer specific code 
end 

#app/models/publisher.rb 
class Publisher < Company 
    publisher specific code 
end 

#app/models/videogame.rb 
class Videogame < ActiveRecord::Base 
    belongs_to :developer, :publisher 
end 

Como resultado, usted tendría Company, desarrollador y editor para que utilice modelos.

Company.find(:all) 
Developer.find(:all) 
Publisher.find(:all) 
Cuestiones relacionadas