2010-10-22 9 views
11

Ich habe zwei Tabellen mit einer vielen zu vielen Beziehung, die ich has_and_belongs_to_many verwendet, um die Zuordnung zu definieren.Erstellen Join-Tabelle ohne Primärschlüssel

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

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

Ich habe auch die Klassentabelle darstellen definiert die Verbindung

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

Wenn ich rake db laufen: Samen ich die folgende Fehlermeldung erhalten:

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

Wenn ich die Datenbank bearbeiten und entfernen Sie das Primärschlüsselfeld (ID) aus der Tabelle bar_foo und führen Sie dann Rake db erneut aus: seed alles funktioniert wie gewünscht.

Angesichts der oben genannten, was ist das bevorzugte Mittel zum Erstellen von Join-Tabellen in Schienen ohne Primärschlüssel?

Ich habe auch versucht mit "has_many: bars,: through =>: foo" und umgekehrt, aber eine Fehlermeldung wie "undefined Methode 'klass' für nil: NilClass".

Antwort

4

Wenn Sie eine HABTM-Assoziation verwenden möchten, sollten Sie kein Modell dafür erstellen - nur eine Tabelle bars_foos mit bar_id und foo_id Integerspalten.

Wenn Sie das Modell dazwischen benötigen (z. B. wenn Sie created_at oder einige andere Attribute der Beziehung verfolgen möchten), können Sie ein zusätzliches Modell hinzufügen, z. Barred und dann würden Sie haben:

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, danke für die Antwort. Ich bin relativ neu in RoR, also was ist das bevorzugte Mittel zum Erstellen einer Tabelle ohne entsprechende Modelldateien? Wäre dies nur möglich, indem Sie eine Migrationsdatei erstellen und create_table verwenden, um die Tabelle mit den beiden Attributen bar_id und foo_id zu definieren? – Keith

+0

Hier ist eine nette Antwort, wie es geht: [Muss ich manuell eine Migration für eine HABTM Join-Tabelle erstellen?] (Http://stackoverflow.com/questions/564306/do-i-need-to-manually-create) -a-migration-fuer-eine-haupt-join-tabelle – Matt

22

Ja, Primärschlüssel nicht für has_and_belongs_to_many erlaubt.

Sie haben zwei Möglichkeiten, dies zu lösen:

Entfernen Sie den Primärschlüssel für die Tabelle. In der Migrationsklasse:

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

Abgesehen davon, werden Sie löschen müssen, entfernen Sie die Datei bar_foo.rb von app/models und auch keine Befestigung und Testdateien, die erzeugt worden sein könnte. Eine gute Idee ist, die script/destroy (oder rails destroy) aufzurufen, um die Dateien zu zerstören und dann die Migration neu zu generieren.

Oder konvertieren 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

Sie brauchen nicht das Modell

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

der has_and_belongs_to_many Verband für eine Tabelle suchen genannt bar_foo in Ihrer Datenbank, was Sie tun müssen, ist ein generieren Migration, um diese Tabelle zu erstellen.

Schienen erzeugen Migration add_table_bar_foo_for_association

dann Sie Ihre Migration bearbeiten und es sollte dieses Ihr Verband sollte

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 

Jetzt arbeiten und auch aussehen, wenn Sie die Zuordnung benötigen zusätzliche Attribute haben Sie auf dem Join kann den has_many :through Weg verwenden und ein diesem zugeordnetes Modell erstellen.

Verwandte Themen