inheritance_test.rb 9.1 KB
Newer Older
1
require "cases/helper"
J
Jeremy Kemper 已提交
2 3 4
require 'models/company'
require 'models/project'
require 'models/subscriber'
D
Initial  
David Heinemeier Hansson 已提交
5

6
class InheritanceTest < ActiveRecord::TestCase
7
  fixtures :companies, :projects, :subscribers, :accounts
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

  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
  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
  end

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  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
  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
  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
  end
D
Initial  
David Heinemeier Hansson 已提交
52

53 54 55 56 57 58 59
  def test_company_descends_from_active_record
    assert_raise(NoMethodError) { ActiveRecord::Base.descends_from_active_record? }
    assert AbstractCompany.descends_from_active_record?, 'AbstractCompany should descend from ActiveRecord::Base'
    assert Company.descends_from_active_record?, 'Company should descend from ActiveRecord::Base'
    assert !Class.new(Company).descends_from_active_record?, 'Company subclass should not descend from ActiveRecord::Base'
  end

60
  def test_a_bad_type_column
61
    #SQLServer need to turn Identity Insert On before manually inserting into the Identity column
62
    if current_adapter?(:SybaseAdapter)
63 64
      Company.connection.execute "SET IDENTITY_INSERT companies ON"
    end
65
    Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')"
66

67
    #We then need to turn it back Off before continuing.
68
    if current_adapter?(:SybaseAdapter)
69 70
      Company.connection.execute "SET IDENTITY_INSERT companies OFF"
    end
71
    assert_raises(ActiveRecord::SubclassNotFound) { Company.find(100) }
D
Initial  
David Heinemeier Hansson 已提交
72 73 74 75 76 77 78 79
  end

  def test_inheritance_find
    assert Company.find(1).kind_of?(Firm), "37signals should be a firm"
    assert Firm.find(1).kind_of?(Firm), "37signals should be a firm"
    assert Company.find(2).kind_of?(Client), "Summit should be a client"
    assert Client.find(2).kind_of?(Client), "Summit should be a client"
  end
J
Jeremy Kemper 已提交
80

D
Initial  
David Heinemeier Hansson 已提交
81 82 83
  def test_alt_inheritance_find
    switch_to_alt_inheritance_column
    test_inheritance_find
84
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
85 86 87
  end

  def test_inheritance_find_all
88
    companies = Company.find(:all, :order => 'id')
D
Initial  
David Heinemeier Hansson 已提交
89 90 91
    assert companies[0].kind_of?(Firm), "37signals should be a firm"
    assert companies[1].kind_of?(Client), "Summit should be a client"
  end
J
Jeremy Kemper 已提交
92

D
Initial  
David Heinemeier Hansson 已提交
93 94 95
  def test_alt_inheritance_find_all
    switch_to_alt_inheritance_column
    test_inheritance_find_all
96
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
97 98 99 100 101 102
  end

  def test_inheritance_save
    firm = Firm.new
    firm.name = "Next Angle"
    firm.save
J
Jeremy Kemper 已提交
103

D
Initial  
David Heinemeier Hansson 已提交
104 105 106
    next_angle = Company.find(firm.id)
    assert next_angle.kind_of?(Firm), "Next Angle should be a firm"
  end
J
Jeremy Kemper 已提交
107

D
Initial  
David Heinemeier Hansson 已提交
108 109 110
  def test_alt_inheritance_save
    switch_to_alt_inheritance_column
    test_inheritance_save
111
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
112 113 114
  end

  def test_inheritance_condition
115
    assert_equal 9, Company.count
116 117
    assert_equal 2, Firm.count
    assert_equal 3, Client.count
D
Initial  
David Heinemeier Hansson 已提交
118
  end
J
Jeremy Kemper 已提交
119

D
Initial  
David Heinemeier Hansson 已提交
120 121 122
  def test_alt_inheritance_condition
    switch_to_alt_inheritance_column
    test_inheritance_condition
123
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
124 125 126 127 128 129
  end

  def test_finding_incorrect_type_data
    assert_raises(ActiveRecord::RecordNotFound) { Firm.find(2) }
    assert_nothing_raised   { Firm.find(1) }
  end
J
Jeremy Kemper 已提交
130

D
Initial  
David Heinemeier Hansson 已提交
131 132 133
  def test_alt_finding_incorrect_type_data
    switch_to_alt_inheritance_column
    test_finding_incorrect_type_data
134
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
135 136 137 138
  end

  def test_update_all_within_inheritance
    Client.update_all "name = 'I am a client'"
139 140
    assert_equal "I am a client", Client.find(:all).first.name
    assert_equal "37signals", Firm.find(:all).first.name
D
Initial  
David Heinemeier Hansson 已提交
141
  end
J
Jeremy Kemper 已提交
142

D
Initial  
David Heinemeier Hansson 已提交
143 144 145
  def test_alt_update_all_within_inheritance
    switch_to_alt_inheritance_column
    test_update_all_within_inheritance
146
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
147 148 149 150
  end

  def test_destroy_all_within_inheritance
    Client.destroy_all
151 152
    assert_equal 0, Client.count
    assert_equal 2, Firm.count
D
Initial  
David Heinemeier Hansson 已提交
153
  end
J
Jeremy Kemper 已提交
154

D
Initial  
David Heinemeier Hansson 已提交
155 156 157
  def test_alt_destroy_all_within_inheritance
    switch_to_alt_inheritance_column
    test_destroy_all_within_inheritance
158
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
159 160 161
  end

  def test_find_first_within_inheritance
162 163 164
    assert_kind_of Firm, Company.find(:first, :conditions => "name = '37signals'")
    assert_kind_of Firm, Firm.find(:first, :conditions => "name = '37signals'")
    assert_nil Client.find(:first, :conditions => "name = '37signals'")
D
Initial  
David Heinemeier Hansson 已提交
165
  end
J
Jeremy Kemper 已提交
166

D
Initial  
David Heinemeier Hansson 已提交
167 168 169
  def test_alt_find_first_within_inheritance
    switch_to_alt_inheritance_column
    test_find_first_within_inheritance
170
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
171 172 173 174
  end

  def test_complex_inheritance
    very_special_client = VerySpecialClient.create("name" => "veryspecial")
175 176 177 178 179
    assert_equal very_special_client, VerySpecialClient.find(:first, :conditions => "name = 'veryspecial'")
    assert_equal very_special_client, SpecialClient.find(:first, :conditions => "name = 'veryspecial'")
    assert_equal very_special_client, Company.find(:first, :conditions => "name = 'veryspecial'")
    assert_equal very_special_client, Client.find(:first, :conditions => "name = 'veryspecial'")
    assert_equal 1, Client.find(:all, :conditions => "name = 'Summit'").size
D
Initial  
David Heinemeier Hansson 已提交
180 181 182 183 184 185
    assert_equal very_special_client, Client.find(very_special_client.id)
  end

  def test_alt_complex_inheritance
    switch_to_alt_inheritance_column
    test_complex_inheritance
186
    switch_to_default_inheritance_column
D
Initial  
David Heinemeier Hansson 已提交
187
  end
J
Jeremy Kemper 已提交
188

189 190 191 192
  def test_eager_load_belongs_to_something_inherited
    account = Account.find(1, :include => :firm)
    assert_not_nil account.instance_variable_get("@firm"), "nil proves eager load failed"
  end
J
Jeremy Kemper 已提交
193

194 195
  def test_eager_load_belongs_to_primary_key_quoting
    con = Account.connection
196
    assert_sql(/\(#{con.quote_table_name('companies')}.#{con.quote_column_name('id')} = 1\)/) do
197 198 199 200
      Account.find(1, :include => :firm)
    end
  end

201 202 203 204 205
  def test_alt_eager_loading
    switch_to_alt_inheritance_column
    test_eager_load_belongs_to_something_inherited
    switch_to_default_inheritance_column
  end
206 207

  def test_inheritance_without_mapping
208
    assert_kind_of SpecialSubscriber, SpecialSubscriber.find("webster132")
209
    assert_nothing_raised { s = SpecialSubscriber.new("name" => "And breaaaaathe!"); s.id = 'roger'; s.save }
210 211 212 213 214
  end

  private
    def switch_to_alt_inheritance_column
      # we don't want misleading test results, so get rid of the values in the type column
215
      Company.find(:all, :order => 'id').each do |c|
216 217 218
        c['type'] = nil
        c.save
      end
219
      [ Company, Firm, Client].each { |klass| klass.reset_column_information }
220
      Company.set_inheritance_column('ruby_type')
221 222 223
    end
    def switch_to_default_inheritance_column
      [ Company, Firm, Client].each { |klass| klass.reset_column_information }
224
      Company.set_inheritance_column('type')
225
    end
226
end
227 228


229
class InheritanceComputeTypeTest < ActiveRecord::TestCase
230 231 232
  fixtures :companies

  def setup
233
    ActiveSupport::Dependencies.log_activity = true
234 235 236
  end

  def teardown
237
    ActiveSupport::Dependencies.log_activity = false
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
    self.class.const_remove :FirmOnTheFly rescue nil
    Firm.const_remove :FirmOnTheFly rescue nil
  end

  def test_instantiation_doesnt_try_to_require_corresponding_file
    foo = Firm.find(:first).clone
    foo.ruby_type = foo.type = 'FirmOnTheFly'
    foo.save!

    # 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 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) }
  end
end