2010-10-22 19 views
11

Ho due tabelle con una relazione molti a molti che sto usando has_and_belongs_to_many per definire l'associazione.Crea tabella join senza chiave primaria

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

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

ho anche la classe definita per rappresentare il tavolo

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

Quando eseguo rake db registrazione: seme ottengo il seguente errore:

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

Se modifico il database e rimuovi il campo chiave primario (ID) dalla tabella bar_foo e poi rerun rake db: seed tutto funziona come desiderato.

Considerato quanto sopra, qual è il mezzo preferito per creare tabelle di join in rotaie senza chiave primaria?

Ho anche provato a utilizzare "has_many: bars,: through =>: foo" e viceversa, ma ho ricevuto un messaggio di errore come "metodo non definito 'klass' per nil: NilClass".

risposta

4

Se si desidera utilizzare un'associazione HABTM non è necessario creare un modello per esso, ma solo una tabella bars_foos con colonne intere bar_id e foo_id.

Se è necessario il modello intermedio (ad esempio se si desidera tenere traccia di created_at o di alcuni altri attributi della relazione) è possibile aggiungere altro modello, ad es. Barred e quindi si avrebbe:

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, grazie per la risposta. Sono relativamente nuovo a RoR quindi qual è il mezzo preferito per creare una tabella senza file modello corrispondenti? Questo dovrebbe essere fatto generando un file di migrazione e usando create_table per definire la tabella con i due attributi bar_id e foo_id? – Keith

+0

Ecco una bella risposta su come farlo: [Devo creare manualmente una migrazione per una tabella di join HABTM?] (Http://stackoverflow.com/questions/564306/do-i-need-to-manually-create -a-migrazione-per-a-HABTM-join-table) – Matt

22

Sì, la chiave primaria non è permesso per has_and_belongs_to_many.

Hai 2 modi per risolvere questo:

Rimuovere la chiave primaria su quel tavolo. Nella classe di migrazione:

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

Oltre a questo, si dovrà eliminare il file bar_foo.rb da app/models e rimuovere anche eventuali file fissaggio e di test che potrebbero essere stati generati. Una buona idea è chiamare lo script/destroy (o rails destroy) per distruggere i file e quindi rigenerare la migrazione.

o convertire in 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

Non è necessario il modello

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

l'associazione has_and_belongs_to_many cercherà una tabella denominata bar_foo nel database quello che dovete fare è generare un migrazione per creare questa tabella.

rotaie generano add_table_bar_foo_for_association migrazione

quindi si modifica la migrazione e dovrebbe assomigliare a questo

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 

Ora la vostra associazione dovrebbe funzionare e anche se è necessario l'associazione di avere attributi extra sul unirsi a voi può usare il modo has_many :through e creare un modello associato a questo.

Problemi correlati