【问题标题】:Create join table with no primary key创建没有主键的连接表
【发布时间】:2011-04-29 05:06:15
【问题描述】:

我有两个具有多对多关系的表,我使用 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 => :foo”,反之亦然,但收到类似“undefined method 'klass' for nil:NilClass”的错误消息。

【问题讨论】:

    标签: ruby-on-rails join primary-key has-and-belongs-to-many


    【解决方案1】:

    你不需要模型

    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 方式并创建一个与之关联的模型。

    【讨论】:

      【解决方案2】:

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

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

      删除该表上的主键。在您的迁移课程中:

      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】:

        如果您想使用 HABTM 关联,​​则不应为其创建模型 - 只需一个表 bars_foosbar_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
        

        【讨论】:

        • 马特,感谢您的回复。我对 RoR 比较陌生,那么创建没有相应模型文件的表的首选方法是什么?这是否可以通过生成迁移文件并使用 create_table 来定义具有 bar_id 和 foo_id 两个属性的表来完成?
        猜你喜欢
        • 1970-01-01
        • 2019-06-06
        • 2011-07-23
        • 2020-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        相关资源
        最近更新 更多