Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Don't try to get the subclass if the inheritance column doesn't exist

The `subclass_from_attrs` method is called even if the column specified by
the `inheritance_column` setting doesn't exist. This prevents setting associations
via the attributes hash if the association name clashes with the value of the setting,
typically `:type`. This worked previously in Rails 3.2.

(cherry picked from commit e8d1d84)

Conflicts:
	activerecord/CHANGELOG.md
	activerecord/test/schema/schema.rb
  • Loading branch information...
commit fd2d1449bc241b1c8ed63b4b83ba40d47ddef4b6 1 parent fc93b5b
@ujjwalt ujjwalt authored pixeltrix committed
View
9 activerecord/CHANGELOG.md
@@ -1,3 +1,12 @@
+* Don't try to get the subclass if the inheritance column doesn't exist
+
+ The `subclass_from_attrs` method is called even if the column specified by
+ the `inheritance_column` setting doesn't exist. This prevents setting associations
+ via the attributes hash if the association name clashes with the value of the setting,
+ typically `:type`. This worked previously in Rails 3.2.
+
+ *Ujjwal Thaakar*
+
* Fix bug in `becomes!` when changing from the base model to a STI sub-class.
Fixes #13272.
View
22 activerecord/lib/active_record/inheritance.rb
@@ -18,13 +18,17 @@ def new(*args, &block)
if abstract_class? || self == Base
raise NotImplementedError, "#{self} is an abstract class and can not be instantiated."
end
- if (attrs = args.first).is_a?(Hash)
- if subclass = subclass_from_attrs(attrs)
- return subclass.new(*args, &block)
- end
+
+ attrs = args.first
+ if subclass_from_attributes?(attrs)
+ subclass = subclass_from_attributes(attrs)
+ end
+
+ if subclass
+ subclass.new(*args, &block)
+ else
+ super
end
- # Delegate to the original .new
- super
end
# True if this isn't a concrete subclass needing a STI type condition.
@@ -168,7 +172,11 @@ 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_attrs(attrs)
+ def subclass_from_attributes?(attrs)
+ columns_hash.include?(inheritance_column) && attrs.is_a?(Hash)
+ end
+
+ def subclass_from_attributes(attrs)
subclass_name = attrs.with_indifferent_access[inheritance_column]
if subclass_name.present? && subclass_name != self.name
View
9 activerecord/test/cases/inheritance_test.rb
@@ -1,10 +1,11 @@
-require "cases/helper"
+require 'cases/helper'
require 'models/company'
require 'models/person'
require 'models/post'
require 'models/project'
require 'models/subscriber'
require 'models/vegetables'
+require 'models/shop'
class InheritanceTest < ActiveRecord::TestCase
fixtures :companies, :projects, :subscribers, :accounts, :vegetables
@@ -367,4 +368,10 @@ def test_instantiation_doesnt_try_to_require_corresponding_file
ensure
ActiveRecord::Base.store_full_sti_class = true
end
+
+ def test_sti_type_from_attributes_disabled_in_non_sti_class
+ phone = Shop::Product::Type.new(name: 'Phone')
+ product = Shop::Product.new(:type => phone)
+ assert product.save
+ end
end
View
5 activerecord/test/models/shop.rb
@@ -5,6 +5,11 @@ class Collection < ActiveRecord::Base
class Product < ActiveRecord::Base
has_many :variants, :dependent => :delete_all
+ belongs_to :type
+
+ class Type < ActiveRecord::Base
+ has_many :products
+ end
end
class Variant < ActiveRecord::Base
View
5 activerecord/test/schema/schema.rb
@@ -555,9 +555,14 @@ def create_table(*args, &block)
create_table :products, :force => true do |t|
t.references :collection
+ t.references :type
t.string :name
end
+ create_table :product_types, :force => true do |t|
+ t.string :name
+ end
+
create_table :projects, :force => true do |t|
t.string :name
t.string :type
Please sign in to comment.
Something went wrong with that request. Please try again.