reflection_test.rb 10.1 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
require 'models/tagging'
D
Initial  
David Heinemeier Hansson 已提交
11

12
class ReflectionTest < ActiveRecord::TestCase
13 14
  include ActiveRecord::Reflection

15
  fixtures :topics, :customers, :companies, :subscribers, :price_estimates
16

D
Initial  
David Heinemeier Hansson 已提交
17 18 19 20
  def setup
    @first = Topic.find(1)
  end

21
  def test_human_name
22 23
    assert_equal "Price estimate", PriceEstimate.model_name.human
    assert_equal "Subscriber", Subscriber.model_name.human
24 25
  end

D
Initial  
David Heinemeier Hansson 已提交
26 27
  def test_read_attribute_names
    assert_equal(
P
Pratik Naik 已提交
28
      %w( id title author_name author_email_address bonus_time written_on last_read content group approved replies_count parent_id parent_title type created_at updated_at ).sort,
29
      @first.attribute_names.sort
D
Initial  
David Heinemeier Hansson 已提交
30 31
    )
  end
32

D
Initial  
David Heinemeier Hansson 已提交
33
  def test_columns
P
Pratik Naik 已提交
34
    assert_equal 16, Topic.columns.length
D
Initial  
David Heinemeier Hansson 已提交
35 36
  end

37 38
  def test_columns_are_returned_in_the_order_they_were_declared
    column_names = Topic.columns.map { |column| column.name }
P
Pratik Naik 已提交
39
    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 created_at updated_at), column_names
40 41
  end

D
Initial  
David Heinemeier Hansson 已提交
42
  def test_content_columns
43 44
    content_columns        = Topic.content_columns
    content_column_names   = content_columns.map {|column| column.name}
P
Pratik Naik 已提交
45 46
    assert_equal 12, content_columns.length
    assert_equal %w(title author_name author_email_address written_on bonus_time last_read content group approved parent_title created_at updated_at).sort, content_column_names.sort
D
Initial  
David Heinemeier Hansson 已提交
47
  end
48

D
Initial  
David Heinemeier Hansson 已提交
49 50 51 52
  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 已提交
53

54 55 56 57 58
  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 已提交
59 60 61 62

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

D
Initial  
David Heinemeier Hansson 已提交
64 65
  def test_integer_columns
    assert_equal :integer, @first.column_for_attribute("id").type
66
  end
D
Initial  
David Heinemeier Hansson 已提交
67

68
  def test_reflection_klass_for_nested_class_name
69
    reflection = MacroReflection.new(nil, nil, { :class_name => 'MyApplication::Business::Company' }, nil)
70 71 72 73 74
    assert_nothing_raised do
      assert_equal MyApplication::Business::Company, reflection.klass
    end
  end

D
Initial  
David Heinemeier Hansson 已提交
75
  def test_aggregation_reflection
76
    reflection_for_address = AggregateReflection.new(
77
      :composed_of, :address, { :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer
D
Initial  
David Heinemeier Hansson 已提交
78 79
    )

80
    reflection_for_balance = AggregateReflection.new(
81
      :composed_of, :balance, { :class_name => "Money", :mapping => %w(balance amount) }, Customer
D
Initial  
David Heinemeier Hansson 已提交
82 83
    )

84
    reflection_for_gps_location = AggregateReflection.new(
85 86 87
      :composed_of, :gps_location, { }, Customer
    )

88 89 90
    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)
91

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

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

96
    assert_equal Money, Customer.reflect_on_aggregation(:balance).klass
D
Initial  
David Heinemeier Hansson 已提交
97
  end
98

99 100 101 102 103 104 105 106 107
  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

108
  def test_has_many_reflection
109
    reflection_for_clients = AssociationReflection.new(:has_many, :clients, { :order => "id", :dependent => :destroy }, Firm)
D
Initial  
David Heinemeier Hansson 已提交
110 111 112 113

    assert_equal reflection_for_clients, Firm.reflect_on_association(:clients)

    assert_equal Client, Firm.reflect_on_association(:clients).klass
114 115
    assert_equal 'companies', Firm.reflect_on_association(:clients).table_name

D
Initial  
David Heinemeier Hansson 已提交
116
    assert_equal Client, Firm.reflect_on_association(:clients_of_firm).klass
117 118 119 120
    assert_equal 'companies', Firm.reflect_on_association(:clients_of_firm).table_name
  end

  def test_has_one_reflection
121
    reflection_for_account = AssociationReflection.new(:has_one, :account, { :foreign_key => "firm_id", :dependent => :destroy }, Firm)
122 123 124 125
    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 已提交
126
  end
127

128 129 130 131 132 133 134 135 136
  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 已提交
137
  def test_association_reflection_in_modules
138
    ActiveRecord::Base.store_full_sti_class = false
139

140 141 142 143 144 145 146 147 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
    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'
175 176
  ensure
    ActiveRecord::Base.store_full_sti_class = true
D
Initial  
David Heinemeier Hansson 已提交
177
  end
J
Jeremy Kemper 已提交
178

179
  def test_reflection_of_all_associations
180
    # FIXME these assertions bust a lot
181 182
    assert_equal 37, Firm.reflect_on_all_associations.size
    assert_equal 27, Firm.reflect_on_all_associations(:has_many).size
183
    assert_equal 10, Firm.reflect_on_all_associations(:has_one).size
184
    assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
185
  end
186

187 188 189 190
  def test_reflection_should_not_raise_error_when_compared_to_other_object
    assert_nothing_raised { Firm.reflections[:clients] == Object.new }
  end

191
  def test_has_many_through_reflection
192
    assert_kind_of ThroughReflection, Subscriber.reflect_on_association(:books)
193 194
  end

195 196 197
  def test_association_primary_key
    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
198
    assert_equal "id", Tagging.reflect_on_association(:taggable).association_primary_key.to_s
199 200
  end

201 202 203 204 205
  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

206
  def test_collection_association
207 208
    assert Pirate.reflect_on_association(:birds).collection?
    assert Pirate.reflect_on_association(:parrots).collection?
209

210 211
    assert !Pirate.reflect_on_association(:ship).collection?
    assert !Ship.reflect_on_association(:pirate).collection?
212 213
  end

214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
  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

243 244 245 246 247 248 249
  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
250
end