1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

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.
This commit is contained in:
Ujjwal Thaakar 2014-01-14 18:53:45 +05:30
parent b242b2dbe7
commit e8d1d84837
No known key found for this signature in database
GPG key ID: F2E7CC9323B99106
5 changed files with 42 additions and 8 deletions

View file

@ -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*
* Enum mappings are now exposed via class methods instead of constants.
Example:

View file

@ -18,13 +18,17 @@ module ActiveRecord
if abstract_class? || self == Base
raise NotImplementedError, "#{self} is an abstract class and cannot 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
# Returns +true+ if this does not need STI type condition. Returns
@ -172,7 +176,11 @@ 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_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 file

@ -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 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase
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 file

@ -5,6 +5,11 @@ module Shop
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 file

@ -557,9 +557,14 @@ ActiveRecord::Schema.define do
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