2010-10-22 127 views
11

我有兩個表具有多對多關係,我使用has_and_belongs_to_many來定義關聯。創建沒有主鍵的連接表

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

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

我也有類定義爲代表的連接表

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

當我運行耙分貝:種子我得到以下錯誤:

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

如果我編輯數據庫並從bar_foo表中刪除主鍵字段(ID),然後重新運行rake數據庫:種子一切正常。

鑑於上述情況,在沒有主鍵的rails中創建連接表的首選方法是什麼?

我也嘗試使用「has_many:bars,:through =>:foo」,反之亦然,但得到了類似「未定義的方法'klass'for nil:NilClass」的錯誤消息。

回答

4

如果你想使用HABTM關聯,你不應該爲它創建一個模型 - bars_foos表中有bar_idfoo_id整數列。

如果您需要介於兩者之間的模型(例如,如果您想跟蹤created_at或關係的某些其他屬性),則可以添加其他模型,例如, Barred,然後你必須:

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

馬特,謝謝你的回覆。我對RoR比較陌生,所以創建沒有相應模型文件的表的首選方法是什麼?這只是通過生成一個遷移文件並使用create_table來定義具有兩個屬性bar_id和foo_id的表來完成的? – Keith 2010-10-22 15:10:58

+0

下面是一個很好的答案:[我需要手動創建HABTM連接表的遷移嗎?](http://stackoverflow.com/questions/564306/do-i-need-to-manually-create -a遷移-FOR-A-HABTM聯接表) – Matt 2010-10-22 15:27:09

22

是,主鍵不允許has_and_belongs_to_many

你有2種方法來解決這個問題:

刪除該表的主鍵。在遷移類:

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

除此之外,你將不得不從app/models刪除文件bar_foo.rb,並刪除可能已產生的任何固定裝置和測試文件。一個好主意是調用script/destroy(或rails destroy)銷燬文件,然後重新生成遷移。

或轉換到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

你並不需要的型號

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

has_and_belongs_to_many協會將一個表稱爲搜索數據庫中的bar_foo你需要做的是產生什麼遷移來創建此表。

軌產生遷移add_table_bar_foo_for_association

然後編輯您的遷移,它應該是這樣的

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 

現在您的關聯應該工作,如果你還需要聯想到對加入你額外的屬性可以使用has_many :through方式並創建與此相關的模型。