我有两个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键.