Skip to content

Commit

Permalink
[Fix rails#51720] Infer association klass as top level if model has s…
Browse files Browse the repository at this point in the history
…ame demodularized name
  • Loading branch information
joshuay03 committed May 3, 2024
1 parent 793ff00 commit b27ccdb
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
8 changes: 6 additions & 2 deletions activerecord/lib/active_record/reflection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -422,13 +422,17 @@ def autosave=(autosave)
# a new association object. Use +build_association+ or +create_association+
# instead. This allows plugins to hook into association object creation.
def klass
@klass ||= compute_class(class_name)
@klass ||= compute_class(compute_name(class_name))
end

def compute_class(name)
name.constantize
end

def compute_name(name) # :nodoc:
active_record.name.demodulize == name ? "::#{name}" : name
end

# Returns +true+ if +self+ and +other_aggregation+ have the same +name+ attribute, +active_record+ attribute,
# and +other_aggregation+ has an options hash assigned to it.
def ==(other_aggregation)
Expand Down Expand Up @@ -979,7 +983,7 @@ def through_reflection?
end

def klass
@klass ||= delegate_reflection.compute_class(class_name)
@klass ||= delegate_reflection.compute_class(compute_name(class_name))
end

# Returns the source of the through reflection. It checks both a singularized
Expand Down
27 changes: 27 additions & 0 deletions activerecord/test/cases/reflection_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
require "models/user_with_invalid_relation"
require "models/hardback"
require "models/sharded/comment"
require "models/admin"
require "models/admin/user"
require "models/user"

class ReflectionTest < ActiveRecord::TestCase
include ActiveRecord::Reflection
Expand Down Expand Up @@ -181,6 +184,30 @@ def test_reflection_klass_requires_ar_subclass
end
end

def test_reflection_klass_with_same_demodularized_name
reflection = ActiveRecord::Reflection.create(
:has_one,
:user,
nil,
{},
Admin::User
)

assert_equal User, reflection.klass
end

def test_reflection_klass_with_same_demodularized_different_modularized_name
reflection = ActiveRecord::Reflection.create(
:has_one,
:user,
nil,
{ class_name: "Nested::User" },
Admin::User
)

assert_equal Nested::User, reflection.klass
end

def test_aggregation_reflection
reflection_for_address = AggregateReflection.new(
:address, nil, { mapping: [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer
Expand Down
6 changes: 6 additions & 0 deletions activerecord/test/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ class User < ActiveRecord::Base
class UserWithNotification < User
after_create -> { Notification.create! message: "A new user has been created." }
end

module Nested
class User < ActiveRecord::Base
self.table_name = "users"
end
end

0 comments on commit b27ccdb

Please sign in to comment.