提交 3da890f8 编写于 作者: Y Yves Senn

Merge pull request #17169 from kuldeepaggarwal/fix-STI-default-type

STI cast new instances to `default type` on initialize.
* 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.
......
......@@ -51,8 +51,8 @@ def new(*args, &block)
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 @@ def type_condition(table = arel_table)
# 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
......
......@@ -478,4 +478,25 @@ def test_sti_type_from_attributes_disabled_in_non_sti_class
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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册