Вам необходимо указать другой первичный ключ для отношения , если вы хотите достичь того, что вы хотите сделать.
Чтобы уточнить, это не то же самое, что изменение primary_key
от модели.Этот способ изменяет только первичный ключ, используемый отношениями.Пожалуйста, смотрите нижнюю часть этого поста для примеров.
Я изменил ключи с обоих с помощью custom_id
и изменил одну на foo_id
.Таким образом, у вас есть лучшее представление о том, что происходит между моделями.Вы можете использовать оба custom_id
, если хотите, но я бы посоветовал сохранить норму рельсов foo_id
для ассоциации own_to.
Если вы хотите использовать оба из custom_id, вам нужно добавить некоторые конкретные foreign_keys
Вот модели:
Foo
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 определяется как foo через custom_id: 100
, но foo все еще находится с ключом id: 1
, а не с ключом custom_id
.