创建没有主键的连接表

创建没有主键的连接表

问题描述:

我有两个表具有多对多关系,我使用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”的错误消息。

如果你想使用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

是,主键不允许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 

你并不需要的型号

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方式并创建与此相关的模型。