2010-10-22 13 views
11

Tengo dos tablas con una relación de muchos a muchos que estoy usando has_and_belongs_to_ many para definir la asociación.Crear tabla de unión sin clave principal

class Foo < ActiveRecord::Base 
    ... 
    has_and_belongs_to_many :bar 
    ... 
end 

class Bar < ActiveRecord::Base 
    ... 
    has_and_belongs_to_many :foo 
    ... 
end 

También he la clase definida para representar la tabla

class BarFoo < ActiveRecord::Base 
    ... 
    belongs_to :foo 
    belongs_to :bar 
    ... 
end 

Cuando corro rake db se unen: la semilla me sale el siguiente error:

Primary key is not allowed in a has_and_belongs_to_many join table (bar_foo) 

Si puedo editar la base de datos y elimine el campo de clave principal (ID) de la tabla bar_foo y luego vuelva a ejecutar rake db: todo funciona como lo desee.

Dado lo anterior, ¿cuál es el medio preferido para crear tablas de unión en rieles sin clave principal?

También intenté usar "has_many: bars,: through =>: foo" y viceversa, pero recibí un mensaje de error algo así como "método indefinido 'klass' para nil: NilClass".

Respuesta

4

Si desea utilizar una asociación HABTM, no debe crear un modelo para ella, solo una tabla bars_foos con bar_id y foo_id columnas enteras.

Si necesita el modelo intermedio (por ejemplo, si desea realizar un seguimiento de created_at u otros atributos de la relación), puede agregar un modelo adicional, p. Barred y entonces tendría que:

class Foo < ActiveRecord::Base 
    ... 
    has_many :bars, :through => :barred 
    ... 
end 

class Bar < ActiveRecord::Base 
    ... 
    has_many :foos, :through => :barred 
    ... 
end 

class Barred < ActiveRecord::Base 
    has_many :bars 
    has_many :foos 
end 
+0

Matt, gracias por la respuesta. Soy relativamente nuevo en RoR, entonces, ¿cuál es el medio preferido para crear una tabla sin los archivos de modelo correspondientes? ¿Esto se haría simplemente generando un archivo de migración y usando create_table para definir la tabla con los dos atributos bar_id y foo_id? – Keith

+0

Aquí hay una buena respuesta sobre cómo hacerlo: [¿Debo crear manualmente una migración para una tabla de unión HABTM?] (Http://stackoverflow.com/questions/564306/do-i-need-to-manually-create -a-migration-for-a-habtm-join-table) – Matt

22

Sí, la clave principal no está permitido para has_and_belongs_to_many.

Tienes 2 maneras de resolver este:

retire la llave primaria en esa mesa. En su clase de la migración:

create_table :bar_foo, :id => false do |t| 
    t.integer :bar_id 
    t.integer :foo_id 
end 

Aparte de esto, tendrá que eliminar el archivo de bar_foo.rbapp/models y también eliminar cualquier archivos de datos y pruebas que podrían haber sido generados. Una buena idea es llamar al script/destroy (o rails destroy) para destruir los archivos y luego regenerar la migración.

o convertir a has_many :through

class Foo < ActiveRecord::Base 
    ... 
    has_many :bar_foos 
    has_many :bars, :through => :bar_foos 
    ... 
end 

class Bar < ActiveRecord::Base 
    ... 
    has_many :bar_foos 
    has_many :foos, :through => :bar_foos 
    ... 
end 

class BarFoo < ActiveRecord::Base 
    ... 
    belongs_to :foo 
    belongs_to :bar 
    ... 
end 
3

No es necesario el modelo

class BarFoo < ActiveRecord::Base 
    ... 
    belongs_to :foo 
    belongs_to :bar 
    ... 
end 

la asociación has_and_belongs_to_many buscará una tabla llamada bar_foo en su base de datos lo que hay que hacer es generar una migración para crear esta tabla.

rieles generan add_table_bar_foo_for_association migración

continuación, edita su migración y que debe tener este aspecto

class AddTableBarFooForAssociation < ActiveRecord::Migration 
    def up 
    create_table :bar_foo, :id => false do |t| 
     t.references :bar 
     t.references :foo 
    end 
    end 

    def down 
    drop_table :bar_foo 
    end 
end 

Ahora su asociación debe trabajar y también si necesita la asociación a tener atributos adicionales en el que unirse puede usar la forma has_many :through y crear un modelo asociado a esto.

Cuestiones relacionadas