aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuldeep Aggarwal <kd.engineer@yahoo.co.in>2015-12-02 16:08:19 +0530
committerKuldeep Aggarwal <kd.engineer@yahoo.co.in>2015-12-02 16:11:24 +0530
commit6b18bdd00ce1e8eb4a5a30f0f6152e47da9bec42 (patch)
tree05b29c3da5f57315b5d39c1f58c1c5d200a7abd9
parent203db6b8c11532eb99e2770dbba326579532aa37 (diff)
downloadrails-6b18bdd00ce1e8eb4a5a30f0f6152e47da9bec42.tar.gz
rails-6b18bdd00ce1e8eb4a5a30f0f6152e47da9bec42.tar.bz2
rails-6b18bdd00ce1e8eb4a5a30f0f6152e47da9bec42.zip
STI cast new instances to `default type` on initialize.
fixes #17121
-rw-r--r--activerecord/CHANGELOG.md10
-rw-r--r--activerecord/lib/active_record/inheritance.rb12
-rw-r--r--activerecord/test/cases/inheritance_test.rb20
3 files changed, 42 insertions, 0 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 79faa9326d..e0ce0af9d6 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,13 @@
+* Use the default inheritance `:type` when instantiating a new object.
+
+ Example:
+
+ # In the schema, BaseModel specifies 'SubType' as the default `:type` value
+ subtype = BaseModel.new
+ assert_equals SubType, subtype.class
+
+ *Kuldeep Aggarwal*
+
* Fix `rake db:structure:dump` on Postgres when multiple schemas are used.
Fixes #22346.
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index 8b719e0bcb..ed95b30f80 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -55,6 +55,8 @@ module ActiveRecord
subclass = subclass_from_attributes(attrs)
end
+ subclass ||= subclass_from_defaults
+
if subclass && subclass != self
subclass.new(*args, &block)
else
@@ -201,6 +203,16 @@ module ActiveRecord
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_defaults
+ if subclass_from_defaults?
+ find_sti_class(columns_hash[inheritance_column].default)
+ end
+ end
+
def subclass_from_attributes(attrs)
attrs = attrs.to_h if attrs.respond_to?(:permitted?)
subclass_name = attrs.with_indifferent_access[inheritance_column]
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index 52e3734dd0..e7709c04c8 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -478,4 +478,24 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase
product = Shop::Product.new(:type => phone)
assert product.save
end
+
+ def test_inheritance_new_with_subclass_as_default
+ 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')
+ assert_equal 'Firm', firm.type
+ assert_instance_of Firm, firm
+ firm = Company.new # this is the case when attrs is nil
+ assert_equal 'Firm', firm.type
+ assert_instance_of Firm, firm
+ firm = Company.new(type: 'Client')
+ assert_equal 'Client', firm.type
+ assert_instance_of Client, firm
+ ensure
+ ActiveRecord::Base.connection.change_column_default :companies, :type, original_type
+ Company.reset_column_information
+ end
end