reflection_test.rb 11.8 KB
Newer Older
1
require "cases/helper"
J
Jeremy Kemper 已提交
2 3 4 5 6
require 'models/topic'
require 'models/customer'
require 'models/company'
require 'models/company_in_module'
require 'models/subscriber'
7
require 'models/ship'
8
require 'models/pirate'
9
require 'models/price_estimate'
10 11 12 13 14 15 16 17 18 19
require 'models/essay'
require 'models/author'
require 'models/organization'
require 'models/post'
require 'models/tagging'
require 'models/category'
require 'models/book'
require 'models/subscriber'
require 'models/subscription'
require 'models/tag'
D
Initial  
David Heinemeier Hansson 已提交
20

21
class ReflectionTest < ActiveRecord::TestCase
22 23
  include ActiveRecord::Reflection

24
  fixtures :topics, :customers, :companies, :subscribers, :price_estimates
25

D
Initial  
David Heinemeier Hansson 已提交
26 27 28 29
  def setup
    @first = Topic.find(1)
  end

30
  def test_human_name
31 32
    assert_equal "Price estimate", PriceEstimate.model_name.human
    assert_equal "Subscriber", Subscriber.model_name.human
33 34
  end

D
Initial  
David Heinemeier Hansson 已提交
35 36
  def test_read_attribute_names
    assert_equal(
37
      %w( id title author_name author_email_address bonus_time written_on last_read content group approved replies_count parent_id parent_title type ).sort,
D
Initial  
David Heinemeier Hansson 已提交
38 39 40
      @first.attribute_names
    )
  end
41

D
Initial  
David Heinemeier Hansson 已提交
42
  def test_columns
43
    assert_equal 14, Topic.columns.length
D
Initial  
David Heinemeier Hansson 已提交
44 45
  end

46 47
  def test_columns_are_returned_in_the_order_they_were_declared
    column_names = Topic.columns.map { |column| column.name }
48
    assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id parent_title type group), column_names
49 50
  end

D
Initial  
David Heinemeier Hansson 已提交
51
  def test_content_columns
52 53
    content_columns        = Topic.content_columns
    content_column_names   = content_columns.map {|column| column.name}
54 55
    assert_equal 10, content_columns.length
    assert_equal %w(title author_name author_email_address written_on bonus_time last_read content group approved parent_title).sort, content_column_names.sort
D
Initial  
David Heinemeier Hansson 已提交
56
  end
57

D
Initial  
David Heinemeier Hansson 已提交
58 59 60 61
  def test_column_string_type_and_limit
    assert_equal :string, @first.column_for_attribute("title").type
    assert_equal 255, @first.column_for_attribute("title").limit
  end
J
Jeremy Kemper 已提交
62

63 64 65 66 67
  def test_column_null_not_null
    subscriber = Subscriber.find(:first)
    assert subscriber.column_for_attribute("name").null
    assert !subscriber.column_for_attribute("nick").null
  end
D
Initial  
David Heinemeier Hansson 已提交
68 69 70 71

  def test_human_name_for_column
    assert_equal "Author name", @first.column_for_attribute("author_name").human_name
  end
72

D
Initial  
David Heinemeier Hansson 已提交
73 74
  def test_integer_columns
    assert_equal :integer, @first.column_for_attribute("id").type
75
  end
D
Initial  
David Heinemeier Hansson 已提交
76

77
  def test_reflection_klass_for_nested_class_name
78
    reflection = MacroReflection.new(nil, nil, { :class_name => 'MyApplication::Business::Company' }, nil)
79 80 81 82 83
    assert_nothing_raised do
      assert_equal MyApplication::Business::Company, reflection.klass
    end
  end

D
Initial  
David Heinemeier Hansson 已提交
84
  def test_aggregation_reflection
85
    reflection_for_address = AggregateReflection.new(
86
      :composed_of, :address, { :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer
D
Initial  
David Heinemeier Hansson 已提交
87 88
    )

89
    reflection_for_balance = AggregateReflection.new(
90
      :composed_of, :balance, { :class_name => "Money", :mapping => %w(balance amount) }, Customer
D
Initial  
David Heinemeier Hansson 已提交
91 92
    )

93
    reflection_for_gps_location = AggregateReflection.new(
94 95 96
      :composed_of, :gps_location, { }, Customer
    )

97 98 99
    assert Customer.reflect_on_all_aggregations.include?(reflection_for_gps_location)
    assert Customer.reflect_on_all_aggregations.include?(reflection_for_balance)
    assert Customer.reflect_on_all_aggregations.include?(reflection_for_address)
100

D
Initial  
David Heinemeier Hansson 已提交
101
    assert_equal reflection_for_address, Customer.reflect_on_aggregation(:address)
102

D
Initial  
David Heinemeier Hansson 已提交
103
    assert_equal Address, Customer.reflect_on_aggregation(:address).klass
J
Jeremy Kemper 已提交
104

105
    assert_equal Money, Customer.reflect_on_aggregation(:balance).klass
D
Initial  
David Heinemeier Hansson 已提交
106
  end
107

108 109 110 111 112 113 114 115 116
  def test_reflect_on_all_autosave_associations
    expected = Pirate.reflect_on_all_associations.select { |r| r.options[:autosave] }
    received = Pirate.reflect_on_all_autosave_associations

    assert !received.empty?
    assert_not_equal Pirate.reflect_on_all_associations.length, received.length
    assert_equal expected, received
  end

117
  def test_has_many_reflection
118
    reflection_for_clients = AssociationReflection.new(:has_many, :clients, { :order => "id", :dependent => :destroy }, Firm)
D
Initial  
David Heinemeier Hansson 已提交
119 120 121 122

    assert_equal reflection_for_clients, Firm.reflect_on_association(:clients)

    assert_equal Client, Firm.reflect_on_association(:clients).klass
123 124
    assert_equal 'companies', Firm.reflect_on_association(:clients).table_name

D
Initial  
David Heinemeier Hansson 已提交
125
    assert_equal Client, Firm.reflect_on_association(:clients_of_firm).klass
126 127 128 129
    assert_equal 'companies', Firm.reflect_on_association(:clients_of_firm).table_name
  end

  def test_has_one_reflection
130
    reflection_for_account = AssociationReflection.new(:has_one, :account, { :foreign_key => "firm_id", :dependent => :destroy }, Firm)
131 132 133 134
    assert_equal reflection_for_account, Firm.reflect_on_association(:account)

    assert_equal Account, Firm.reflect_on_association(:account).klass
    assert_equal 'accounts', Firm.reflect_on_association(:account).table_name
D
Initial  
David Heinemeier Hansson 已提交
135
  end
136

137 138 139 140 141 142 143 144 145
  def test_belongs_to_inferred_foreign_key_from_assoc_name
    Company.belongs_to :foo
    assert_equal "foo_id", Company.reflect_on_association(:foo).primary_key_name
    Company.belongs_to :bar, :class_name => "Xyzzy"
    assert_equal "bar_id", Company.reflect_on_association(:bar).primary_key_name
    Company.belongs_to :baz, :class_name => "Xyzzy", :foreign_key => "xyzzy_id"
    assert_equal "xyzzy_id", Company.reflect_on_association(:baz).primary_key_name
  end

D
Initial  
David Heinemeier Hansson 已提交
146
  def test_association_reflection_in_modules
147
    ActiveRecord::Base.store_full_sti_class = false
148

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
    assert_reflection MyApplication::Business::Firm,
      :clients_of_firm,
      :klass      => MyApplication::Business::Client,
      :class_name => 'Client',
      :table_name => 'companies'

    assert_reflection MyApplication::Billing::Account,
      :firm,
      :klass      => MyApplication::Business::Firm,
      :class_name => 'MyApplication::Business::Firm',
      :table_name => 'companies'

    assert_reflection MyApplication::Billing::Account,
      :qualified_billing_firm,
      :klass      => MyApplication::Billing::Firm,
      :class_name => 'MyApplication::Billing::Firm',
      :table_name => 'companies'

    assert_reflection MyApplication::Billing::Account,
      :unqualified_billing_firm,
      :klass      => MyApplication::Billing::Firm,
      :class_name => 'Firm',
      :table_name => 'companies'

    assert_reflection MyApplication::Billing::Account,
      :nested_qualified_billing_firm,
      :klass      => MyApplication::Billing::Nested::Firm,
      :class_name => 'MyApplication::Billing::Nested::Firm',
      :table_name => 'companies'

    assert_reflection MyApplication::Billing::Account,
      :nested_unqualified_billing_firm,
      :klass      => MyApplication::Billing::Nested::Firm,
      :class_name => 'Nested::Firm',
      :table_name => 'companies'
184 185
  ensure
    ActiveRecord::Base.store_full_sti_class = true
D
Initial  
David Heinemeier Hansson 已提交
186
  end
J
Jeremy Kemper 已提交
187

188
  def test_reflection_of_all_associations
189
    # FIXME these assertions bust a lot
190 191
    assert_equal 37, Firm.reflect_on_all_associations.size
    assert_equal 27, Firm.reflect_on_all_associations(:has_many).size
192
    assert_equal 10, Firm.reflect_on_all_associations(:has_one).size
193
    assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
194
  end
195

196 197 198 199
  def test_reflection_should_not_raise_error_when_compared_to_other_object
    assert_nothing_raised { Firm.reflections[:clients] == Object.new }
  end

200
  def test_has_many_through_reflection
201
    assert_kind_of ThroughReflection, Subscriber.reflect_on_association(:books)
202
  end
J
Jon Leighton 已提交
203

204 205 206 207 208 209 210
  def test_through_reflection_chain
    expected = [
      Author.reflect_on_association(:essay_categories),
      Author.reflect_on_association(:essays),
      Organization.reflect_on_association(:authors)
    ]
    actual = Organization.reflect_on_association(:author_essay_categories).through_reflection_chain
J
Jon Leighton 已提交
211

212 213
    assert_equal expected, actual
  end
J
Jon Leighton 已提交
214

215 216 217 218 219 220 221 222
  def test_through_conditions
    expected = [
      ["tags.name = 'Blue'"],
      ["taggings.comment = 'first'"],
      ["posts.title LIKE 'misc post%'"]
    ]
    actual = Author.reflect_on_association(:misc_post_first_blue_tags).through_conditions
    assert_equal expected, actual
J
Jon Leighton 已提交
223

224 225 226 227 228 229 230 231
    expected = [
      ["tags.name = 'Blue'", "taggings.comment = 'first'", "posts.title LIKE 'misc post%'"],
      [],
      []
    ]
    actual = Author.reflect_on_association(:misc_post_first_blue_tags_2).through_conditions
    assert_equal expected, actual
  end
J
Jon Leighton 已提交
232

233 234 235
  def test_nested?
    assert !Author.reflect_on_association(:comments).nested?
    assert Author.reflect_on_association(:tags).nested?
J
Jon Leighton 已提交
236

237 238 239 240
    # Only goes :through once, but the through_reflection is a has_and_belongs_to_many, so this is
    # a nested through association
    assert Category.reflect_on_association(:post_comments).nested?
  end
J
Jon Leighton 已提交
241

242 243 244 245
  def test_association_primary_key
    # Normal association
    assert_equal "id",   Author.reflect_on_association(:posts).association_primary_key.to_s
    assert_equal "name", Author.reflect_on_association(:essay).association_primary_key.to_s
J
Jon Leighton 已提交
246

247 248 249 250 251
    # Through association (uses the :primary_key option from the source reflection)
    assert_equal "nick", Author.reflect_on_association(:subscribers).association_primary_key.to_s
    assert_equal "name", Author.reflect_on_association(:essay_category).association_primary_key.to_s
    assert_equal "custom_primary_key", Author.reflect_on_association(:tags_with_primary_key).association_primary_key.to_s # nested
  end
J
Jon Leighton 已提交
252

253 254 255 256
  def test_active_record_primary_key
    assert_equal "nick", Subscriber.reflect_on_association(:subscriptions).active_record_primary_key.to_s
    assert_equal "name", Author.reflect_on_association(:essay).active_record_primary_key.to_s
  end
257

258
  def test_collection_association
259 260
    assert Pirate.reflect_on_association(:birds).collection?
    assert Pirate.reflect_on_association(:parrots).collection?
261

262 263
    assert !Pirate.reflect_on_association(:ship).collection?
    assert !Ship.reflect_on_association(:pirate).collection?
264 265
  end

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
  def test_default_association_validation
    assert AssociationReflection.new(:has_many, :clients, {}, Firm).validate?

    assert !AssociationReflection.new(:has_one, :client, {}, Firm).validate?
    assert !AssociationReflection.new(:belongs_to, :client, {}, Firm).validate?
    assert !AssociationReflection.new(:has_and_belongs_to_many, :clients, {}, Firm).validate?
  end

  def test_always_validate_association_if_explicit
    assert AssociationReflection.new(:has_one, :client, { :validate => true }, Firm).validate?
    assert AssociationReflection.new(:belongs_to, :client, { :validate => true }, Firm).validate?
    assert AssociationReflection.new(:has_many, :clients, { :validate => true }, Firm).validate?
    assert AssociationReflection.new(:has_and_belongs_to_many, :clients, { :validate => true }, Firm).validate?
  end

  def test_validate_association_if_autosave
    assert AssociationReflection.new(:has_one, :client, { :autosave => true }, Firm).validate?
    assert AssociationReflection.new(:belongs_to, :client, { :autosave => true }, Firm).validate?
    assert AssociationReflection.new(:has_many, :clients, { :autosave => true }, Firm).validate?
    assert AssociationReflection.new(:has_and_belongs_to_many, :clients, { :autosave => true }, Firm).validate?
  end

  def test_never_validate_association_if_explicit
    assert !AssociationReflection.new(:has_one, :client, { :autosave => true, :validate => false }, Firm).validate?
    assert !AssociationReflection.new(:belongs_to, :client, { :autosave => true, :validate => false }, Firm).validate?
    assert !AssociationReflection.new(:has_many, :clients, { :autosave => true, :validate => false }, Firm).validate?
    assert !AssociationReflection.new(:has_and_belongs_to_many, :clients, { :autosave => true, :validate => false }, Firm).validate?
  end

295 296 297 298 299 300 301
  private
    def assert_reflection(klass, association, options)
      assert reflection = klass.reflect_on_association(association)
      options.each do |method, value|
        assert_equal(value, reflection.send(method))
      end
    end
302
end