diff options
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/inheritance.rb | 32 | ||||
-rw-r--r-- | activerecord/test/cases/inheritance_test.rb | 11 |
3 files changed, 23 insertions, 27 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index e0ce0af9d6..89ba579e80 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,8 +1,11 @@ -* Use the default inheritance `:type` when instantiating a new object. +* Respect the column default values for `inheritance_column` when + instantiating records through the base class. + + Fixes #17121. Example: - # In the schema, BaseModel specifies 'SubType' as the default `:type` value + # The schema of BaseModel has `t.string :type, default: 'SubType'` subtype = BaseModel.new assert_equals SubType, subtype.class diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index ed95b30f80..4ae9920efb 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -51,12 +51,10 @@ module ActiveRecord end attrs = args.first - if subclass_from_attributes?(attrs) - subclass = subclass_from_attributes(attrs) + if attribute_names.include?(inheritance_column) + subclass = subclass_from_attributes(attrs) || subclass_from_defaults end - subclass ||= subclass_from_defaults - if subclass && subclass != self subclass.new(*args, &block) else @@ -199,26 +197,20 @@ module ActiveRecord # is not self or a valid subclass, raises ActiveRecord::SubclassNotFound # If this is a StrongParameters hash, and access to inheritance_column is not permitted, # this will ignore the inheritance column and return nil - def subclass_from_attributes?(attrs) - attribute_names.include?(inheritance_column) && (attrs.is_a?(Hash) || attrs.respond_to?(:permitted?)) - end - - def subclass_from_defaults? - attribute_names.include?(inheritance_column) && columns_hash[inheritance_column].try(:default) - end + def subclass_from_attributes(attrs) + attrs = attrs.to_h if attrs.respond_to?(:permitted?) + if attrs.is_a?(Hash) + subclass_name = attrs.with_indifferent_access[inheritance_column] - def subclass_from_defaults - if subclass_from_defaults? - find_sti_class(columns_hash[inheritance_column].default) + if subclass_name.present? + find_sti_class(subclass_name) + end end end - def subclass_from_attributes(attrs) - attrs = attrs.to_h if attrs.respond_to?(:permitted?) - subclass_name = attrs.with_indifferent_access[inheritance_column] - - if subclass_name.present? - find_sti_class(subclass_name) + def subclass_from_defaults + if default = columns_hash[inheritance_column].default + find_sti_class(default) end end end diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index e7709c04c8..2ad8b30eae 100644 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -483,15 +483,16 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase original_type = Company.columns_hash["type"].default ActiveRecord::Base.connection.change_column_default :companies, :type, 'Firm' Company.reset_column_information - # this is the case when attrs is a +Hash+, but we didn't specify the type, - # so we need default type. - firm = Company.new(firm_name: 'Shri Hans Plastic') + + firm = Company.new # without arguments assert_equal 'Firm', firm.type assert_instance_of Firm, firm - firm = Company.new # this is the case when attrs is nil + + firm = Company.new(firm_name: 'Shri Hans Plastic') # with arguments assert_equal 'Firm', firm.type assert_instance_of Firm, firm - firm = Company.new(type: 'Client') + + firm = Company.new(type: 'Client') # overwrite the default type assert_equal 'Client', firm.type assert_instance_of Client, firm ensure |