aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/inheritance.rb32
-rw-r--r--activerecord/test/cases/inheritance_test.rb11
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