Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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.