Open
Description
Reproduction:
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "rails", github: "rails/rails", branch: "main"
gem "pg"
end
require "active_record/railtie"
require "minitest/autorun"
# This connection will do for database-independent bug reports.
ENV["DATABASE_URL"] = "postgresql:test"
class TestApp < Rails::Application
config.load_defaults Rails::VERSION::STRING.to_f
config.eager_load = false
config.logger = Logger.new($stdout)
config.secret_key_base = "secret_key_base"
config.active_record.encryption.primary_key = "primary_key"
config.active_record.encryption.deterministic_key = "deterministic_key"
config.active_record.encryption.key_derivation_salt = "key_derivation_salt"
end
Rails.application.initialize!
ActiveRecord::Schema.define do
create_table :posts_with_uuids, force: true, id: false do |t|
t.uuid :uuid, primary_key: true, default: -> { "gen_random_uuid()" }
end
create_table :comments_with_uuids, force: true, id: false do |t|
t.uuid :uuid, primary_key: true, default: -> { "gen_random_uuid()" }
t.uuid :post_uuid
t.boolean :special
end
create_table :posts_with_ids_and_uuids, force: true do |t|
t.uuid :uuid, default: -> { "gen_random_uuid()" }
end
create_table :comments_with_ids_and_uuids, force: true do |t|
t.uuid :uuid, default: -> { "gen_random_uuid()" }
t.uuid :post_uuid
t.boolean :special
end
end
class PostWithUUID < ActiveRecord::Base
self.table_name = :posts_with_uuids
has_many :comments_with_uuids, class_name: :CommentWithUUID,
foreign_key: :post_uuid,
primary_key: :uuid,
inverse_of: :post_with_uuid
has_one :special_comment_with_uuid, -> { where(special: true) }, class_name: :CommentWithUUID,
foreign_key: :post_uuid,
primary_key: :uuid,
inverse_of: :post_with_uuid
end
class CommentWithUUID < ActiveRecord::Base
self.table_name = :comments_with_uuids
belongs_to :post_with_uuid, class_name: :PostWithUUID, foreign_key: :post_uuid, primary_key: :uuid
end
class PostWithIdAndUUID < ActiveRecord::Base
self.table_name = :posts_with_ids_and_uuids
has_many :comments_with_ids_and_uuids, class_name: :CommentWithIdAndUUID,
foreign_key: :post_uuid,
primary_key: :uuid,
inverse_of: :post_with_id_and_uuid
has_one :special_comment_with_id_and_uuid, -> { where(special: true) }, class_name: :CommentWithIdAndUUID,
foreign_key: :post_uuid,
primary_key: :uuid,
inverse_of: :post_with_id_and_uuid
end
class CommentWithIdAndUUID < ActiveRecord::Base
self.table_name = :comments_with_ids_and_uuids
belongs_to :post_with_id_and_uuid, class_name: :PostWithIdAndUUID, foreign_key: :post_uuid, primary_key: :uuid
end
class BugTest < ActiveSupport::TestCase
def test_has_many_association_inverse_with_similar_association_pk_and_owner_pk
post = PostWithUUID.create!
post.comments_with_uuids.create!
post.reload
assert_same post, post.comments_with_uuids.first.post_with_uuid # ✅
end
def test_has_one_association_inverse_with_similar_association_pk_and_owner_pk
post = PostWithUUID.create!
post.comments_with_uuids.create!(special: true)
post.reload
assert_same post, post.special_comment_with_uuid.post_with_uuid # ✅
end
def test_has_many_association_inverse_with_different_association_pk_and_owner_pk
post = PostWithIdAndUUID.create!
post.comments_with_ids_and_uuids.create!
post.reload
assert_same post, post.comments_with_ids_and_uuids.first.post_with_id_and_uuid # ❌
end
def test_has_one_association_inverse_with_different_association_pk_and_owner_pk
post = PostWithIdAndUUID.create!
post.comments_with_ids_and_uuids.create!(special: true)
post.reload
assert_same post, post.special_comment_with_id_and_uuid.post_with_id_and_uuid # ❌
end
end
Tested this from 7.1 to main and it consistently fails.