From cbd66b430b6553e468bcdaa94af661a2d8b69d81 Mon Sep 17 00:00:00 2001 From: Alex Robbin Date: Thu, 26 Mar 2015 13:26:19 -0400 Subject: [PATCH] allow setting of a demodulized class name when using STI If your STI class looks like this: ```ruby class Company < ActiveRecord::Base self.store_full_sti_class = false class GoodCo < Company end class BadCo < Company end end ``` The expectation (which is valid) is that the `type` in the database is saved as `GoodCo` or `BadCo`. However, another expectation should be that setting `type` to `GoodCo` would correctly instantiate the object as a `Company::GoodCo`. That second expectation is what this should fix. --- activerecord/CHANGELOG.md | 4 ++++ activerecord/lib/active_record/inheritance.rb | 14 ++++++++------ activerecord/test/cases/inheritance_test.rb | 8 ++++++++ activerecord/test/models/company.rb | 3 +++ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 09045087d9..d02d8912a3 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Allow setting of a demodulized class name whenusing single table inheritance. + + *Alex Robbin* + * Dump indexes in `create_table` instead of `add_index`. If the adapter supports indexes in create table, generated SQL is diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index 24098f72dc..a7801963e8 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -198,14 +198,16 @@ def subclass_from_attributes?(attrs) def subclass_from_attributes(attrs) subclass_name = attrs.with_indifferent_access[inheritance_column] - if subclass_name.present? && subclass_name != self.name - subclass = subclass_name.safe_constantize + if subclass_name.present? + subclass = find_sti_class(subclass_name) - unless descendants.include?(subclass) - raise ActiveRecord::SubclassNotFound.new("Invalid single-table inheritance type: #{subclass_name} is not a subclass of #{name}") - end + if subclass.name != self.name + unless descendants.include?(subclass) + raise ActiveRecord::SubclassNotFound.new("Invalid single-table inheritance type: #{subclass_name} is not a subclass of #{name}") + end - subclass + subclass + end end end end diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index 278fa63e04..9199066072 100644 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -217,6 +217,14 @@ def test_new_with_complex_inheritance assert_nothing_raised { Client.new(type: 'VerySpecialClient') } end + def test_new_without_storing_full_sti_class + without_store_full_sti_class do + Company::SpecialCo # force autoloading + item = Company.new(type: 'SpecialCo') + assert_instance_of Company::SpecialCo, item + end + end + def test_new_with_autoload_paths path = File.expand_path('../../models/autoloadable', __FILE__) ActiveSupport::Dependencies.autoload_paths << path diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index 6961f8fd6f..67936e8e5d 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -26,6 +26,9 @@ def arbitrary_method def private_method "I am Jack's innermost fears and aspirations" end + + class SpecialCo < Company + end end module Namespaced -- GitLab