Mon*_*odr 6 activerecord ruby-on-rails ruby-on-rails-5
陷入困境 - 乍一看 - RoR中的简单问题.我相信这很容易,但是在SO中没有人回答太多帮助我.
我有两个ActiveRecord模型:Foo有很多Bars:
class Foo < ApplicationRecord
has_many :bars
end
class Bar < ApplicationRecord
belongs_to :foo
end
Run Code Online (Sandbox Code Playgroud)
这就像一个魅力.但我想使用另一个Fooforeign_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
Run Code Online (Sandbox Code Playgroud)
但这不起作用.即ActiveRecord的不断结合Foo来Bars使用foo_id.
注意:在Foo中包含self.primary_key ='custom_id'可以部分工作.但我认为这不是一个好主意.我想保持foo_id为主键
更新:
鉴于反馈 - 谢谢你们 - 我在这里上传了这个例子https://github.com/montenegrodr/temporary_repository_ror:
更新#2:
答案不符合上述问题.为什么测试失败,我的假设是它不会失败.
更新#3:
我还需要评估一些新的答案.将在24小时内完成.谢谢.
更新#4:
谢谢你们所有答案.但他们都没有满足标准.我需要通过测试.如果不可能,有人可以解释原因吗?这是铁轨限制吗?
你需要指定一个不同的主键的关系,如果你想实现你在找什么做的。
澄清一下,这与更改primary_key模型的 不同。这种方式只是改变关系使用的主键。请参阅本文底部的示例。
我将密钥从 usingcustom_id更改为foo_id. 通过这种方式,您可以更好地了解模型之间发生的情况。custom_id如果您愿意,您可以同时使用两者,但我建议保留foo_idbelongs_to 关联的rails 规范。
如果您想同时使用 custom_id,则必须添加一些特定的 foreign_keys
富
class Foo < ApplicationRecord
has_many :bars,
primary_key: :custom_id,
foreign_key: :foo_id
end
Run Code Online (Sandbox Code Playgroud)
酒吧
class Bar < ApplicationRecord
belongs_to :foo,
primary_key: :custom_id
end
Run Code Online (Sandbox Code Playgroud)
创建Foos
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
Run Code Online (Sandbox Code Playgroud)
创建条
class CreateBars < ActiveRecord::Migration[5.2]
def change
create_table :bars do |t|
t.integer :foo_id, index: true
t.timestamps
end
end
end
Run Code Online (Sandbox Code Playgroud)
这是现在应该通过的更新测试:
测试
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
Run Code Online (Sandbox Code Playgroud)
例子
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
Run Code Online (Sandbox Code Playgroud)
如您所见,此方法不会更改Foo自身的主键。它改变了主键Foo和Bar使用之间的关系。Bar 是通过custom_id: 100foo关联到 foo 的,但是 foo 仍然可以通过它的id: 1键而不是它的custom_id键找到。
| 归档时间: |
|
| 查看次数: |
880 次 |
| 最近记录: |