ruby-on-rails – 如何使用不同的列作为外键强制has_many关联

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 如何使用不同的列作为外键强制has_many关联前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
陷入困境 – 乍一看 – RoR中的简单问题.我相信这很容易,但是在SO中没有人回答太多帮助我.

我有两个ActiveRecord模型:Foo有很多条:

class Foo < ApplicationRecord
    has_many :bars
end

class Bar < ApplicationRecord
  belongs_to :foo
end

这就像一个魅力.但我想使用Foo的另一个字段作为foreign_key.默认是foo_id我想使用custom_id作为我的外键.所以我尝试了这个(因为网上建议的解决方案很多):

class Foo < ApplicationRecord
    has_many :bars,:foreign_key => 'custom_id',:class_name => 'Bars'
end

class Bars < ApplicationRecord
  belongs_to :foo,:class_name => 'Foo'
end

但这不起作用.即ActiveRecord使用foo_id将Foo绑定到Bars.

注意:在Foo中包含self.primary_key =’custom_id’可以部分工作.但我认为这不是一个好主意.我想保持foo_id为主键

更新:

鉴于反馈 – 谢谢你们 – 我在这里上传了这个例子https://github.com/montenegrodr/temporary_repository_ror

> Bar model
> Foo model
> ** This test is expected to PASS but it FAILS. **

更新#2:

答案不符合上述问题.为什么测试失败,我的假设是它不会失败.

更新#3:

我还需要评估一些新的答案.将在24小时内完成.谢谢.

更新#4:

谢谢你们所有答案.但他们都没有满足标准.我需要通过测试.如果不可能,有人可以解释原因吗?这是铁轨限制吗?

解决方法

如果您希望实现您想要的目标,则需要为关系指定不同的主键.

为了澄清,这与更改模型的primary_key不同.这种方式只是更改关系使用的主键.有关示例,请参阅本文的底部.

我使用custom_id更改了两个键,并将其更改为foo_id.通过这种方式,您可以更好地了解模型之间的情况.如果您愿意,可以同时使用custom_id,但我建议保留belongs_to关联的foo_id的rails规范.

如果要同时使用custom_id,则必须添加一些特定的foreign_key

以下是模型:

class Foo < ApplicationRecord
  has_many :bars,primary_key: :custom_id,foreign_key: :foo_id
end

酒吧

class Bar < ApplicationRecord
  belongs_to :foo,primary_key: :custom_id
end

迁移

CreateFoos

class CreateFoos < ActiveRecord::Migration[5.2]
  def change
    create_table :foos do |t|

      t.integer :custom_id,index: {unique: true}
      t.timestamps
    end
  end
end

CreateBars

class CreateBars < ActiveRecord::Migration[5.2]
  def change
    create_table :bars do |t|

      t.integer :foo_id,index: true
      t.timestamps
    end
  end
end

这是现在应该传递的更新的测试:

测试

require 'test_helper'

class BarTest < ActiveSupport::TestCase
  test "the truth" do
    foo = Foo.new(id: 1,custom_id: 100)
    bar = Bar.new(foo: foo)

    assert bar.foo_id == foo.custom_id
    # bar.foo_id    = 100
    # foo.custom_id = 100
  end
end

例子

Foo.find(1) #<Foo id: 1,custom_id: 100>
Bar.first #<Bar id: 1,foo_id: 100>

Bar.first.foo = #<Foo id: 1,custom_id: 100>
Bar.first.foo == Foo.find(1) # true

如您所见,此方法不会更改Foo本身的主键.它改变了Foo和Bar之间关系使用的主键. Bar通过custom_id:100重新定义为foo,但foo仍然找到它的id:1键,而不是它的custom_id键.

猜你在找的Ruby相关文章