relations_test.rb 12.6 KB
Newer Older
1
require "cases/helper"
2 3
require 'models/tag'
require 'models/tagging'
4 5
require 'models/post'
require 'models/topic'
6
require 'models/comment'
7 8
require 'models/reply'
require 'models/author'
9
require 'models/comment'
10 11 12 13
require 'models/entrant'
require 'models/developer'
require 'models/company'

E
Emilio Tagua 已提交
14
class RelationTest < ActiveRecord::TestCase
15 16
  fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
    :taggings
17

18 19 20 21 22 23
  def test_scoped
    topics = Topic.scoped
    assert_kind_of ActiveRecord::Relation, topics
    assert_equal 4, topics.size
  end

24 25 26 27 28 29
  def test_scoped_all
    topics = Topic.scoped.all
    assert_kind_of Array, topics
    assert_no_queries { assert_equal 4, topics.size }
  end

P
Pratik Naik 已提交
30 31 32 33 34 35 36 37 38 39 40
  def test_loaded_all
    topics = Topic.scoped

    assert_queries(1) do
      2.times { assert_equal 4, topics.all.size }
    end

    assert topics.loaded?
  end

  def test_scoped_first
P
Pratik Naik 已提交
41
    topics = Topic.scoped.order('id ASC')
P
Pratik Naik 已提交
42 43 44 45 46 47 48 49 50

    assert_queries(1) do
      2.times { assert_equal "The First Topic", topics.first.title }
    end

    assert ! topics.loaded?
  end

  def test_loaded_first
P
Pratik Naik 已提交
51
    topics = Topic.scoped.order('id ASC')
P
Pratik Naik 已提交
52 53 54 55 56 57 58 59 60

    assert_queries(1) do
      topics.all # force load
      2.times { assert_equal "The First Topic", topics.first.title }
    end

    assert topics.loaded?
  end

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
  def test_reload
    topics = Topic.scoped

    assert_queries(1) do
      2.times { topics.to_a }
    end

    assert topics.loaded?

    topics.reload
    assert ! topics.loaded?

    assert_queries(1) { topics.to_a }
  end

76
  def test_finding_with_conditions
77 78
    assert_equal ["David"], Author.where(:name => 'David').map(&:name)
    assert_equal ['Mary'],  Author.where(["name = ?", 'Mary']).map(&:name)
79
    assert_equal ['Mary'],  Author.where("name = ?", 'Mary').map(&:name)
80 81 82
  end

  def test_finding_with_order
83
    topics = Topic.order('id')
84
    assert_equal 4, topics.to_a.size
85 86 87 88
    assert_equal topics(:first).title, topics.first.title
  end

  def test_finding_with_order_and_take
89
    entrants = Entrant.order("id ASC").limit(2).to_a
90

P
Pratik Naik 已提交
91 92
    assert_equal 2, entrants.size
    assert_equal entrants(:first).name, entrants.first.name
93 94 95
  end

  def test_finding_with_order_limit_and_offset
96
    entrants = Entrant.order("id ASC").limit(2).offset(1)
97

98
    assert_equal 2, entrants.to_a.size
P
Pratik Naik 已提交
99
    assert_equal entrants(:second).name, entrants.first.name
100

101
    entrants = Entrant.order("id ASC").limit(2).offset(2)
102
    assert_equal 1, entrants.to_a.size
P
Pratik Naik 已提交
103
    assert_equal entrants(:third).name, entrants.first.name
104 105 106
  end

  def test_finding_with_group
107
    developers = Developer.group("salary").select("salary").to_a
108 109 110 111 112
    assert_equal 4, developers.size
    assert_equal 4, developers.map(&:salary).uniq.size
  end

  def test_finding_with_hash_conditions_on_joined_table
113
    firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a
114 115 116 117 118
    assert_equal 1, firms.size
    assert_equal companies(:rails_core), firms.first
  end

  def test_find_all_with_join
119
    developers_on_project_one = Developer.joins('LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id').
120
      where('project_id=1').to_a
121 122 123 124 125 126 127 128

    assert_equal 3, developers_on_project_one.length
    developer_names = developers_on_project_one.map { |d| d.name }
    assert developer_names.include?('David')
    assert developer_names.include?('Jamis')
  end

  def test_find_on_hash_conditions
129
    assert_equal Topic.find(:all, :conditions => {:approved => false}), Topic.where({ :approved => false }).to_a
130 131 132
  end

  def test_joins_with_string_array
133
    person_with_reader_and_post = Post.joins([
134 135 136 137 138 139
        "INNER JOIN categorizations ON categorizations.post_id = posts.id",
        "INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
      ]
    ).to_a
    assert_equal 1, person_with_reader_and_post.size
  end
140

141 142
  def test_scoped_responds_to_delegated_methods
    relation = Topic.scoped
143 144

    ["map", "uniq", "sort", "insert", "delete", "update"].each do |method|
J
Jeremy Kemper 已提交
145
      assert relation.respond_to?(method), "Topic.all should respond to #{method.inspect}"
146 147
    end
  end
148 149

  def test_find_with_readonly_option
150 151
    Developer.scoped.each { |d| assert !d.readonly? }
    Developer.scoped.readonly.each { |d| assert d.readonly? }
152
  end
153 154

  def test_eager_association_loading_of_stis_with_multiple_references
155
    authors = Author.eager_load(:posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } }).
156
      order('comments.body, very_special_comments_posts.body').where('posts.id = 4').to_a
157

158 159 160 161 162 163 164 165 166
    assert_equal [authors(:david)], authors
    assert_no_queries do
      authors.first.posts.first.special_comments.first.post.special_comments
      authors.first.posts.first.special_comments.first.post.very_special_comment
    end
  end

  def test_find_with_included_associations
    assert_queries(2) do
167
      posts = Post.preload(:comments)
168
      assert posts.first.comments.first
169
    end
170

171
    assert_queries(2) do
172
      posts = Post.preload(:comments).to_a
173
      assert posts.first.comments.first
174
    end
175

176
    assert_queries(2) do
177
      posts = Post.preload(:author)
178
      assert posts.first.author
179
    end
180

181
    assert_queries(2) do
182
      posts = Post.preload(:author).to_a
183 184 185 186 187 188 189
      assert posts.first.author
    end

    assert_queries(3) do
      posts = Post.preload(:author, :comments).to_a
      assert posts.first.author
      assert posts.first.comments.first
190 191
    end
  end
192

P
Pratik Naik 已提交
193
  def test_default_scope_with_conditions_string
194
    assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeveloperCalledDavid.scoped.map(&:id).sort
195 196 197 198
    assert_equal nil, DeveloperCalledDavid.create!.name
  end

  def test_default_scope_with_conditions_hash
199
    assert_equal Developer.find_all_by_name('Jamis').map(&:id).sort, DeveloperCalledJamis.scoped.map(&:id).sort
200 201 202
    assert_equal 'Jamis', DeveloperCalledJamis.create!.name
  end

203 204 205 206 207
  def test_default_scoping_finder_methods
    developers = DeveloperCalledDavid.order('id').map(&:id).sort
    assert_equal Developer.find_all_by_name('David').map(&:id).sort, developers
  end

208 209
  def test_loading_with_one_association
    posts = Post.preload(:comments)
210 211 212 213
    post = posts.find { |p| p.id == 1 }
    assert_equal 2, post.comments.size
    assert post.comments.include?(comments(:greetings))

214
    post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
215 216 217
    assert_equal 2, post.comments.size
    assert post.comments.include?(comments(:greetings))

218
    posts = Post.preload(:last_comment)
219 220 221 222 223
    post = posts.find { |p| p.id == 1 }
    assert_equal Post.find(1).last_comment, post.last_comment
  end

  def test_loading_with_one_association_with_non_preload
224
    posts = Post.eager_load(:last_comment).order('comments.id DESC')
225 226 227
    post = posts.find { |p| p.id == 1 }
    assert_equal Post.find(1).last_comment, post.last_comment
  end
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

  def test_dynamic_find_by_attributes
    david = authors(:david)
    author = Author.preload(:taggings).find_by_id(david.id)
    expected_taggings = taggings(:welcome_general, :thinking_general)

    assert_no_queries do
      assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
    end

    authors = Author.scoped
    assert_equal david, authors.find_by_id_and_name(david.id, david.name)
    assert_equal david, authors.find_by_id_and_name!(david.id, david.name)
  end

  def test_dynamic_find_by_attributes_bang
    author = Author.scoped.find_by_id!(authors(:david).id)
    assert_equal "David", author.name

P
Pratik Naik 已提交
247
    assert_raises(ActiveRecord::RecordNotFound) { Author.scoped.find_by_id_and_name!(20, 'invalid') }
248 249 250 251 252 253 254 255 256
  end

  def test_dynamic_find_all_by_attributes
    authors = Author.scoped

    davids = authors.find_all_by_name('David')
    assert_kind_of Array, davids
    assert_equal [authors(:david)], davids
  end
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277

  def test_dynamic_find_or_initialize_by_attributes
    authors = Author.scoped

    lifo = authors.find_or_initialize_by_name('Lifo')
    assert_equal "Lifo", lifo.name
    assert lifo.new_record?

    assert_equal authors(:david), authors.find_or_initialize_by_name(:name => 'David')
  end

  def test_dynamic_find_or_create_by_attributes
    authors = Author.scoped

    lifo = authors.find_or_create_by_name('Lifo')
    assert_equal "Lifo", lifo.name
    assert ! lifo.new_record?

    assert_equal authors(:david), authors.find_or_create_by_name(:name => 'David')
  end

P
Pratik Naik 已提交
278 279 280 281 282 283
  def test_find_id
    authors = Author.scoped

    david = authors.find(authors(:david).id)
    assert_equal 'David', david.name

P
Pratik Naik 已提交
284
    assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') }
P
Pratik Naik 已提交
285
  end
286

P
Pratik Naik 已提交
287 288 289 290 291 292 293 294 295 296
  def test_find_ids
    authors = Author.order('id ASC')

    results = authors.find(authors(:david).id, authors(:mary).id)
    assert_kind_of Array, results
    assert_equal 2, results.size
    assert_equal 'David', results[0].name
    assert_equal 'Mary', results[1].name
    assert_equal results, authors.find([authors(:david).id, authors(:mary).id])

P
Pratik Naik 已提交
297 298
    assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') }
    assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) }
P
Pratik Naik 已提交
299 300
  end

P
Pratik Naik 已提交
301 302 303 304 305
  def test_exists
    davids = Author.where(:name => 'David')
    assert davids.exists?
    assert davids.exists?(authors(:david).id)
    assert ! davids.exists?(authors(:mary).id)
P
Pratik Naik 已提交
306 307
    assert ! davids.exists?("42")
    assert ! davids.exists?(42)
P
Pratik Naik 已提交
308 309 310 311 312

    fake  = Author.where(:name => 'fake author')
    assert ! fake.exists?
    assert ! fake.exists?(authors(:david).id)
  end
313 314 315 316 317 318

  def test_last
    authors = Author.scoped
    assert_equal authors(:mary), authors.last
  end

P
Pratik Naik 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331
  def test_destroy_all
    davids = Author.where(:name => 'David')

    # Force load
    assert_equal [authors(:david)], davids.to_a
    assert davids.loaded?

    assert_difference('Author.count', -1) { davids.destroy_all }

    assert_equal [], davids.to_a
    assert davids.loaded?
  end

P
Pratik Naik 已提交
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
  def test_delete_all
    davids = Author.where(:name => 'David')

    assert_difference('Author.count', -1) { davids.delete_all }
    assert ! davids.loaded?
  end

  def test_delete_all_loaded
    davids = Author.where(:name => 'David')

    # Force load
    assert_equal [authors(:david)], davids.to_a
    assert davids.loaded?

    assert_difference('Author.count', -1) { davids.delete_all }

    assert_equal [], davids.to_a
    assert davids.loaded?
  end

352 353 354 355
  def test_relation_merging
    devs = Developer.where("salary >= 80000") & Developer.limit(2) & Developer.order('id ASC').where("id < 3")
    assert_equal [developers(:david), developers(:jamis)], devs.to_a

P
Pratik Naik 已提交
356
    dev_with_count = Developer.limit(1) & Developer.order('id DESC') & Developer.select('developers.*')
357
    assert_equal [developers(:poor_jamis)], dev_with_count.to_a
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
  end

  def test_relation_merging_with_eager_load
    relations = []
    relations << (Post.order('comments.id DESC') & Post.eager_load(:last_comment) & Post.scoped)
    relations << (Post.eager_load(:last_comment) & Post.order('comments.id DESC') & Post.scoped)
    
    relations.each do |posts|
      post = posts.find { |p| p.id == 1 }
      assert_equal Post.find(1).last_comment, post.last_comment
    end
  end

  def test_relation_merging_with_preload
    [Post.scoped & Post.preload(:author), Post.preload(:author) & Post.scoped].each do |posts|
      assert_queries(2) { assert posts.first.author }
    end
375
  end
376 377 378 379 380

  def test_invalid_merge
    assert_raises(ArgumentError) { Post.scoped & Developer.scoped }
  end

P
Pratik Naik 已提交
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
  def test_count
    posts = Post.scoped

    assert_equal 7, posts.count
    assert_equal 7, posts.count(:all)
    assert_equal 7, posts.count(:id)

    assert_equal 1, posts.where('comments_count > 1').count
    assert_equal 5, posts.where(:comments_count => 0).count
  end

  def test_count_with_distinct
    posts = Post.scoped

    assert_equal 3, posts.count(:comments_count, :distinct => true)
    assert_equal 7, posts.count(:comments_count, :distinct => false)

    assert_equal 3, posts.select(:comments_count).count(:distinct => true)
    assert_equal 7, posts.select(:comments_count).count(:distinct => false)
  end

  def test_count_explicit_columns
    Post.update_all(:comments_count => nil)
    posts = Post.scoped

    assert_equal 7, posts.select('comments_count').count('id')
    assert_equal 0, posts.select('comments_count').count
    assert_equal 0, posts.count(:comments_count)
    assert_equal 0, posts.count('comments_count')
  end
411 412 413 414 415 416 417 418 419 420 421 422

  def test_size
    posts = Post.scoped

    assert_queries(1) { assert_equal 7, posts.size }
    assert ! posts.loaded?

    best_posts = posts.where(:comments_count => 0)
    best_posts.to_a # force load
    assert_no_queries { assert_equal 5, best_posts.size }
  end

P
Pratik Naik 已提交
423
end