我有两个表有多对多的关系,我使用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
当我运行rake db:seed时出现以下错误:
Primary key is not allowed in a has_and_belongs_to_many join table (bar_foo)
如果我编辑数据库并从bar_foo表中删除主键字段(ID),然后重新运行rake db:seed一切都按预期工作。
鉴于上述情况,在没有主键的rails中创建连接表的首选方法是什么?
我也尝试使用“has_many:bars,:through =&gt;:foo”,反之亦然,但是收到的错误信息类似于“未定义的方法'klass'代表nil:NilClass”。
答案 0 :(得分:24)
是的,has_and_belongs_to_many
不允许使用主键。
您有两种方法可以解决这个问题:
删除该表上的主键。在您的迁移类中:
create_table :bar_foo, :id => false do |t|
t.integer :bar_id
t.integer :foo_id
end
除此之外,您还必须从bar_foo.rb
删除文件app/models
,并删除可能已生成的任何灯具和测试文件。一个好主意是调用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
答案 1 :(得分:4)
如果您想使用HABTM关联,则不应为其创建模型 - 只需使用bars_foos
和bar_id
整数列的表foo_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
答案 2 :(得分:4)
您不需要模型
class BarFoo < ActiveRecord::Base
...
belongs_to :foo
belongs_to :bar
...
end
has_and_belongs_to_many
关联将在您的数据库中搜索名为bar_foo
的表,您需要做的是生成迁移以创建此表。
rails生成迁移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
方式并创建与此关联的模型。