diff options
Diffstat (limited to 'activerecord/test/cases/inheritance_test.rb')
-rw-r--r-- | activerecord/test/cases/inheritance_test.rb | 171 |
1 files changed, 107 insertions, 64 deletions
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index 73cf99a5d7..f67d85603a 100644 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -1,27 +1,45 @@ -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' + +module InheritanceTestHelper + def with_store_full_sti_class(&block) + assign_store_full_sti_class true, &block + end + + def without_store_full_sti_class(&block) + assign_store_full_sti_class false, &block + end + + def assign_store_full_sti_class(flag) + old_store_full_sti_class = ActiveRecord::Base.store_full_sti_class + ActiveRecord::Base.store_full_sti_class = flag + yield + ensure + ActiveRecord::Base.store_full_sti_class = old_store_full_sti_class + end +end class InheritanceTest < ActiveRecord::TestCase + include InheritanceTestHelper fixtures :companies, :projects, :subscribers, :accounts, :vegetables def test_class_with_store_full_sti_class_returns_full_name - old = ActiveRecord::Base.store_full_sti_class - ActiveRecord::Base.store_full_sti_class = true - assert_equal 'Namespaced::Company', Namespaced::Company.sti_name - ensure - ActiveRecord::Base.store_full_sti_class = old + with_store_full_sti_class do + assert_equal 'Namespaced::Company', Namespaced::Company.sti_name + end end def test_class_with_blank_sti_name company = Company.first company = company.dup company.extend(Module.new { - def read_attribute(name) + def _read_attribute(name) return ' ' if name == 'type' super end @@ -32,39 +50,31 @@ class InheritanceTest < ActiveRecord::TestCase end def test_class_without_store_full_sti_class_returns_demodulized_name - old = ActiveRecord::Base.store_full_sti_class - ActiveRecord::Base.store_full_sti_class = false - assert_equal 'Company', Namespaced::Company.sti_name - ensure - ActiveRecord::Base.store_full_sti_class = old + without_store_full_sti_class do + assert_equal 'Company', Namespaced::Company.sti_name + end end def test_should_store_demodulized_class_name_with_store_full_sti_class_option_disabled - old = ActiveRecord::Base.store_full_sti_class - ActiveRecord::Base.store_full_sti_class = false - item = Namespaced::Company.new - assert_equal 'Company', item[:type] - ensure - ActiveRecord::Base.store_full_sti_class = old + without_store_full_sti_class do + item = Namespaced::Company.new + assert_equal 'Company', item[:type] + end end def test_should_store_full_class_name_with_store_full_sti_class_option_enabled - old = ActiveRecord::Base.store_full_sti_class - ActiveRecord::Base.store_full_sti_class = true - item = Namespaced::Company.new - assert_equal 'Namespaced::Company', item[:type] - ensure - ActiveRecord::Base.store_full_sti_class = old + with_store_full_sti_class do + item = Namespaced::Company.new + assert_equal 'Namespaced::Company', item[:type] + end end def test_different_namespace_subclass_should_load_correctly_with_store_full_sti_class_option - old = ActiveRecord::Base.store_full_sti_class - ActiveRecord::Base.store_full_sti_class = true - item = Namespaced::Company.create :name => "Wolverine 2" - assert_not_nil Company.find(item.id) - assert_not_nil Namespaced::Company.find(item.id) - ensure - ActiveRecord::Base.store_full_sti_class = old + with_store_full_sti_class do + item = Namespaced::Company.create name: "Wolverine 2" + assert_not_nil Company.find(item.id) + assert_not_nil Namespaced::Company.find(item.id) + end end def test_company_descends_from_active_record @@ -94,16 +104,8 @@ class InheritanceTest < ActiveRecord::TestCase end def test_a_bad_type_column - #SQLServer need to turn Identity Insert On before manually inserting into the Identity column - if current_adapter?(:SybaseAdapter) - Company.connection.execute "SET IDENTITY_INSERT companies ON" - end Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')" - #We then need to turn it back Off before continuing. - if current_adapter?(:SybaseAdapter) - Company.connection.execute "SET IDENTITY_INSERT companies OFF" - end assert_raise(ActiveRecord::SubclassNotFound) { Company.find(100) } end @@ -128,6 +130,23 @@ class InheritanceTest < ActiveRecord::TestCase assert_kind_of Cabbage, cabbage end + def test_becomes_and_change_tracking_for_inheritance_columns + cucumber = Vegetable.find(1) + cabbage = cucumber.becomes!(Cabbage) + assert_equal ['Cucumber', 'Cabbage'], cabbage.custom_type_change + end + + def test_alt_becomes_bang_resets_inheritance_type_column + vegetable = Vegetable.create!(name: "Red Pepper") + assert_nil vegetable.custom_type + + cabbage = vegetable.becomes!(Cabbage) + assert_equal "Cabbage", cabbage.custom_type + + vegetable = cabbage.becomes!(Vegetable) + assert_nil cabbage.custom_type + end + def test_inheritance_find_all companies = Company.all.merge!(:order => 'id').to_a assert_kind_of Firm, companies[0], "37signals should be a firm" @@ -176,14 +195,14 @@ class InheritanceTest < ActiveRecord::TestCase e = assert_raises(NotImplementedError) do AbstractCompany.new end - assert_equal("AbstractCompany is an abstract class and can not be instantiated.", e.message) + assert_equal("AbstractCompany is an abstract class and cannot be instantiated.", e.message) end def test_new_with_ar_base e = assert_raises(NotImplementedError) do ActiveRecord::Base.new end - assert_equal("ActiveRecord::Base is an abstract class and can not be instantiated.", e.message) + assert_equal("ActiveRecord::Base is an abstract class and cannot be instantiated.", e.message) end def test_new_with_invalid_type @@ -194,10 +213,28 @@ class InheritanceTest < ActiveRecord::TestCase assert_raise(ActiveRecord::SubclassNotFound) { Company.new(:type => 'Account') } end + def test_new_with_unrelated_namespaced_type + without_store_full_sti_class do + e = assert_raises ActiveRecord::SubclassNotFound do + Namespaced::Company.new(type: 'Firm') + end + + assert_equal "Invalid single-table inheritance type: Namespaced::Firm is not a subclass of Namespaced::Company", e.message + end + end + + 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 + 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 @@ -210,9 +247,9 @@ class InheritanceTest < ActiveRecord::TestCase end def test_inheritance_condition - assert_equal 10, Company.count + assert_equal 11, Company.count assert_equal 2, Firm.count - assert_equal 4, Client.count + assert_equal 5, Client.count end def test_alt_inheritance_condition @@ -290,17 +327,17 @@ class InheritanceTest < ActiveRecord::TestCase def test_eager_load_belongs_to_something_inherited account = Account.all.merge!(:includes => :firm).find(1) - assert account.association_cache.key?(:firm), "nil proves eager load failed" + assert account.association(:firm).loaded?, "association was not eager loaded" end def test_alt_eager_loading cabbage = RedCabbage.all.merge!(:includes => :seller).find(4) - assert cabbage.association_cache.key?(:seller), "nil proves eager load failed" + assert cabbage.association(:seller).loaded?, "association was not eager loaded" end def test_eager_load_belongs_to_primary_key_quoting con = Account.connection - assert_sql(/#{con.quote_table_name('companies')}.#{con.quote_column_name('id')} IN \(1\)/) do + assert_sql(/#{con.quote_table_name('companies')}.#{con.quote_column_name('id')} = 1/) do Account.all.merge!(:includes => :firm).find(1) end end @@ -321,39 +358,45 @@ class InheritanceTest < ActiveRecord::TestCase end class InheritanceComputeTypeTest < ActiveRecord::TestCase + include InheritanceTestHelper fixtures :companies def setup ActiveSupport::Dependencies.log_activity = true end - def teardown + teardown do ActiveSupport::Dependencies.log_activity = false self.class.const_remove :FirmOnTheFly rescue nil Firm.const_remove :FirmOnTheFly rescue nil end def test_instantiation_doesnt_try_to_require_corresponding_file - ActiveRecord::Base.store_full_sti_class = false - foo = Firm.first.clone - foo.type = 'FirmOnTheFly' - foo.save! + without_store_full_sti_class do + foo = Firm.first.clone + foo.type = 'FirmOnTheFly' + foo.save! - # Should fail without FirmOnTheFly in the type condition. - assert_raise(ActiveRecord::RecordNotFound) { Firm.find(foo.id) } + # Should fail without FirmOnTheFly in the type condition. + assert_raise(ActiveRecord::RecordNotFound) { Firm.find(foo.id) } - # Nest FirmOnTheFly in the test case where Dependencies won't see it. - self.class.const_set :FirmOnTheFly, Class.new(Firm) - assert_raise(ActiveRecord::SubclassNotFound) { Firm.find(foo.id) } + # Nest FirmOnTheFly in the test case where Dependencies won't see it. + self.class.const_set :FirmOnTheFly, Class.new(Firm) + assert_raise(ActiveRecord::SubclassNotFound) { Firm.find(foo.id) } - # Nest FirmOnTheFly in Firm where Dependencies will see it. - # This is analogous to nesting models in a migration. - Firm.const_set :FirmOnTheFly, Class.new(Firm) + # Nest FirmOnTheFly in Firm where Dependencies will see it. + # This is analogous to nesting models in a migration. + Firm.const_set :FirmOnTheFly, Class.new(Firm) - # And instantiate will find the existing constant rather than trying - # to require firm_on_the_fly. - assert_nothing_raised { assert_kind_of Firm::FirmOnTheFly, Firm.find(foo.id) } - ensure - ActiveRecord::Base.store_full_sti_class = true + # And instantiate will find the existing constant rather than trying + # to require firm_on_the_fly. + assert_nothing_raised { assert_kind_of Firm::FirmOnTheFly, Firm.find(foo.id) } + end + 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 |