aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorYves Senn <yves.senn@gmail.com>2015-12-02 13:31:20 +0100
committerYves Senn <yves.senn@gmail.com>2015-12-02 13:39:30 +0100
commit3da890f891b116218c10d9b049dba23d15d416cf (patch)
tree343746a950fa80b31866c6b2813a0d4828f25a76 /activerecord
parent203db6b8c11532eb99e2770dbba326579532aa37 (diff)
parent6b18bdd00ce1e8eb4a5a30f0f6152e47da9bec42 (diff)
downloadrails-3da890f891b116218c10d9b049dba23d15d416cf.tar.gz
rails-3da890f891b116218c10d9b049dba23d15d416cf.tar.bz2
rails-3da890f891b116218c10d9b049dba23d15d416cf.zip
Merge pull request #17169 from kuldeepaggarwal/fix-STI-default-type
STI cast new instances to `default type` on initialize.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md13
-rw-r--r--activerecord/lib/active_record/inheritance.rb22
-rw-r--r--activerecord/test/cases/inheritance_test.rb21
3 files changed, 47 insertions, 9 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 79faa9326d..89ba579e80 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,16 @@
+* Respect the column default values for `inheritance_column` when
+ instantiating records through the base class.
+
+ Fixes #17121.
+
+ Example:
+
+ # The schema of BaseModel has `t.string :type, default: 'SubType'`
+ 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..4ae9920efb 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -51,8 +51,8 @@ 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
if subclass && subclass != self
@@ -197,16 +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_attributes(attrs)
attrs = attrs.to_h if attrs.respond_to?(:permitted?)
- subclass_name = attrs.with_indifferent_access[inheritance_column]
+ if attrs.is_a?(Hash)
+ subclass_name = attrs.with_indifferent_access[inheritance_column]
+
+ if subclass_name.present?
+ find_sti_class(subclass_name)
+ end
+ end
+ end
- 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 52e3734dd0..2ad8b30eae 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -478,4 +478,25 @@ 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
+
+ firm = Company.new # without arguments
+ assert_equal 'Firm', firm.type
+ assert_instance_of Firm, firm
+
+ 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') # overwrite the default type
+ 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