创建没有主键的连接表

Kei*_*ith 12 join ruby-on-rails primary-key has-and-belongs-to-many

我有两个表与多对多的关系,我使用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
Run Code Online (Sandbox Code Playgroud)

我还定义了表示连接表的类

class BarFoo < ActiveRecord::Base
  ...
  belongs_to :foo
  belongs_to :bar
  ...
end
Run Code Online (Sandbox Code Playgroud)

当我运行rake db:seed时出现以下错误:

Primary key is not allowed in a has_and_belongs_to_many join table (bar_foo)
Run Code Online (Sandbox Code Playgroud)

如果我编辑数据库并从bar_foo表中删除主键字段(ID),然后重新运行rake db:seed一切都按预期工作.

鉴于上述情况,在没有主键的rails中创建连接表的首选方法是什么?

我也尝试使用"has_many:bars,:through =>:foo",反之亦然,但得到的错误信息类似于"未定义的方法'klass'为nil:NilClass".

Swa*_*and 24

是的,不允许使用主键has_and_belongs_to_many.

您有两种方法可以解决这个问题:

删除该表上的主键.在您的迁移类中:

create_table :bar_foo, :id => false do |t|
  t.integer :bar_id
  t.integer :foo_id
end
Run Code Online (Sandbox Code Playgroud)

除此之外,您还必须删除该文件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
Run Code Online (Sandbox Code Playgroud)


Mr_*_*zle 5

你不需要模型

class BarFoo < ActiveRecord::Base
  ...
  belongs_to :foo
  belongs_to :bar
  ...
end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

现在您的关联应该可以工作,并且如果您需要关联在连接上具有额外的属性,您可以使用该has_many :through方式并创建与此关联的模型。


Mat*_*att 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
Run Code Online (Sandbox Code Playgroud)