relations_test.rb 59.6 KB
Newer Older
1 2
# frozen_string_literal: true

3
require "cases/helper"
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
require "models/tag"
require "models/tagging"
require "models/post"
require "models/topic"
require "models/comment"
require "models/author"
require "models/entrant"
require "models/developer"
require "models/computer"
require "models/reply"
require "models/company"
require "models/bird"
require "models/car"
require "models/engine"
require "models/tyre"
require "models/minivan"
20
require "models/possession"
21
require "models/reader"
22
require "models/category"
23
require "models/categorization"
24
require "models/edge"
25

E
Emilio Tagua 已提交
26
class RelationTest < ActiveRecord::TestCase
27
  fixtures :authors, :author_addresses, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :categories_posts, :posts, :comments, :tags, :taggings, :cars, :minivans
28

29 30
  class TopicWithCallbacks < ActiveRecord::Base
    self.table_name = :topics
31
    before_update { |topic| topic.author_name = "David" if topic.author_name.blank? }
32 33
  end

34 35 36
  def test_do_not_double_quote_string_id
    van = Minivan.last
    assert van
37
    assert_equal van.id, Minivan.where(minivan_id: van).to_a.first.minivan_id
38
  end
39

40 41 42
  def test_do_not_double_quote_string_id_with_array
    van = Minivan.last
    assert van
43
    assert_equal van, Minivan.where(minivan_id: [van]).to_a.first
44 45
  end

46
  def test_two_scopes_with_includes_should_not_drop_any_include
47 48 49 50 51
    # heat habtm cache
    car = Car.incl_engines.incl_tyres.first
    car.tyres.length
    car.engines.length

52
    car = Car.incl_engines.incl_tyres.first
53 54
    assert_no_queries { car.tyres.length }
    assert_no_queries { car.engines.length }
55
  end
56

57
  def test_dynamic_finder
58 59
    x = Post.where("author_id = ?", 1)
    assert x.klass.respond_to?(:find_by_id), "@klass should handle dynamic finders"
60 61
  end

62
  def test_multivalue_where
63
    posts = Post.where("author_id = ? AND id = ?", 1, 1)
64 65 66
    assert_equal 1, posts.to_a.size
  end

67
  def test_scoped
68
    topics = Topic.all
69
    assert_kind_of ActiveRecord::Relation, topics
70
    assert_equal 5, topics.size
71 72
  end

73
  def test_to_json
74 75
    assert_nothing_raised  { Bird.all.to_json }
    assert_nothing_raised  { Bird.all.to_a.to_json }
76 77 78
  end

  def test_to_yaml
79 80
    assert_nothing_raised  { Bird.all.to_yaml }
    assert_nothing_raised  { Bird.all.to_a.to_yaml }
81 82
  end

83
  def test_to_xml
84 85
    assert_nothing_raised  { Bird.all.to_xml }
    assert_nothing_raised  { Bird.all.to_a.to_xml }
86 87
  end

88
  def test_scoped_all
89
    topics = Topic.all.to_a
90
    assert_kind_of Array, topics
91
    assert_no_queries { assert_equal 5, topics.size }
92 93
  end

P
Pratik Naik 已提交
94
  def test_loaded_all
95
    topics = Topic.all
P
Pratik Naik 已提交
96 97

    assert_queries(1) do
98
      2.times { assert_equal 5, topics.to_a.size }
P
Pratik Naik 已提交
99 100 101 102 103 104
    end

    assert topics.loaded?
  end

  def test_scoped_first
105
    topics = Topic.all.order("id ASC")
P
Pratik Naik 已提交
106 107 108 109 110 111 112 113 114

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

    assert ! topics.loaded?
  end

  def test_loaded_first
115
    topics = Topic.all.order("id ASC")
116
    topics.load # force load
P
Pratik Naik 已提交
117

118 119 120 121 122 123 124 125
    assert_no_queries do
      assert_equal "The First Topic", topics.first.title
    end

    assert topics.loaded?
  end

  def test_loaded_first_with_limit
126
    topics = Topic.all.order("id ASC")
127
    topics.load # force load
128 129

    assert_no_queries do
130 131
      assert_equal ["The First Topic",
                    "The Second Topic of the day"], topics.first(2).map(&:title)
P
Pratik Naik 已提交
132 133 134 135 136
    end

    assert topics.loaded?
  end

137
  def test_first_get_more_than_available
138
    topics = Topic.all.order("id ASC")
139
    unloaded_first = topics.first(10)
140
    topics.load # force load
141 142 143 144 145 146 147

    assert_no_queries do
      loaded_first = topics.first(10)
      assert_equal unloaded_first, loaded_first
    end
  end

148
  def test_reload
149
    topics = Topic.all
150 151 152 153 154 155 156

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

    assert topics.loaded?

157
    original_size = topics.to_a.size
158
    Topic.create! title: "fake"
159

160 161 162
    assert_queries(1) { topics.reload }
    assert_equal original_size + 1, topics.size
    assert topics.loaded?
163 164
  end

I
Ivan Kukobko 已提交
165
  def test_finding_with_subquery
166
    relation = Topic.where(approved: true)
167 168 169
    assert_equal relation.to_a, Topic.select("*").from(relation).to_a
    assert_equal relation.to_a, Topic.select("subquery.*").from(relation).to_a
    assert_equal relation.to_a, Topic.select("a.*").from(relation, :a).to_a
170 171
  end

172 173
  def test_finding_with_subquery_with_binds
    relation = Post.first.comments
174 175 176
    assert_equal relation.to_a, Comment.select("*").from(relation).to_a
    assert_equal relation.to_a, Comment.select("subquery.*").from(relation).to_a
    assert_equal relation.to_a, Comment.select("a.*").from(relation, :a).to_a
177 178
  end

179 180 181 182 183
  def test_finding_with_subquery_without_select_does_not_change_the_select
    relation = Topic.where(approved: true)
    assert_raises(ActiveRecord::StatementInvalid) do
      Topic.from(relation).to_a
    end
C
Cody Cutrer 已提交
184 185
  end

186
  def test_select_with_subquery_in_from_does_not_use_original_table_name
187
    relation = Comment.group(:type).select("COUNT(post_id) AS post_count, type")
188 189
    subquery = Comment.from(relation).select("type", "post_count")
    assert_equal(relation.map(&:post_count).sort, subquery.map(&:post_count).sort)
190 191 192
  end

  def test_group_with_subquery_in_from_does_not_use_original_table_name
193 194
    relation = Comment.group(:type).select("COUNT(post_id) AS post_count,type")
    subquery = Comment.from(relation).group("type").average("post_count")
195
    assert_equal(relation.map(&:post_count).sort, subquery.values.sort)
196
  end
197

198 199 200 201 202 203 204 205 206
  def test_finding_with_subquery_with_eager_loading_in_from
    relation = Comment.includes(:post).where("posts.type": "Post")
    assert_equal relation.to_a, Comment.select("*").from(relation).to_a
    assert_equal relation.to_a, Comment.select("subquery.*").from(relation).to_a
    assert_equal relation.to_a, Comment.select("a.*").from(relation, :a).to_a
  end

  def test_finding_with_subquery_with_eager_loading_in_where
    relation = Comment.includes(:post).where("posts.type": "Post")
207
    assert_equal relation.sort_by(&:id), Comment.where(id: relation).sort_by(&:id)
208 209
  end

210
  def test_finding_with_conditions
211
    assert_equal ["David"], Author.where(name: "David").map(&:name)
212 213
    assert_equal ["Mary"],  Author.where(["name = ?", "Mary"]).map(&:name)
    assert_equal ["Mary"],  Author.where("name = ?", "Mary").map(&:name)
214 215 216
  end

  def test_finding_with_order
217
    topics = Topic.order("id")
218
    assert_equal 5, topics.to_a.size
219 220 221
    assert_equal topics(:first).title, topics.first.title
  end

222 223
  def test_finding_with_arel_order
    topics = Topic.order(Topic.arel_table[:id].asc)
224
    assert_equal 5, topics.to_a.size
225 226
    assert_equal topics(:first).title, topics.first.title
  end
227

228
  def test_finding_with_assoc_order
229
    topics = Topic.order(id: :desc)
230 231
    assert_equal 5, topics.to_a.size
    assert_equal topics(:fifth).title, topics.first.title
232
  end
233

234 235 236 237 238 239 240
  def test_finding_with_arel_assoc_order
    topics = Topic.order(Arel.sql("id") => :desc)
    assert_equal 5, topics.to_a.size
    assert_equal topics(:fifth).title, topics.first.title
  end

  def test_finding_with_reversed_assoc_order
241
    topics = Topic.order(id: :asc).reverse_order
242 243
    assert_equal 5, topics.to_a.size
    assert_equal topics(:fifth).title, topics.first.title
244
  end
245

246 247 248 249 250 251
  def test_finding_with_reversed_arel_assoc_order
    topics = Topic.order(Arel.sql("id") => :asc).reverse_order
    assert_equal 5, topics.to_a.size
    assert_equal topics(:fifth).title, topics.first.title
  end

252
  def test_reverse_order_with_function
253
    topics = Topic.order(Arel.sql("length(title)")).reverse_order
254 255 256
    assert_equal topics(:second).title, topics.first.title
  end

257 258 259 260 261
  def test_reverse_arel_assoc_order_with_function
    topics = Topic.order(Arel.sql("length(title)") => :asc).reverse_order
    assert_equal topics(:second).title, topics.first.title
  end

262
  def test_reverse_order_with_function_other_predicates
263
    topics = Topic.order(Arel.sql("author_name, length(title), id")).reverse_order
264
    assert_equal topics(:second).title, topics.first.title
265
    topics = Topic.order(Arel.sql("length(author_name), id, length(title)")).reverse_order
266 267 268 269 270
    assert_equal topics(:fifth).title, topics.first.title
  end

  def test_reverse_order_with_multiargument_function
    assert_raises(ActiveRecord::IrreversibleOrderError) do
271
      Topic.order(Arel.sql("concat(author_name, title)")).reverse_order
272
    end
273
    assert_raises(ActiveRecord::IrreversibleOrderError) do
274
      Topic.order(Arel.sql("concat(lower(author_name), title)")).reverse_order
275 276
    end
    assert_raises(ActiveRecord::IrreversibleOrderError) do
277
      Topic.order(Arel.sql("concat(author_name, lower(title))")).reverse_order
278 279
    end
    assert_raises(ActiveRecord::IrreversibleOrderError) do
280
      Topic.order(Arel.sql("concat(lower(author_name), title, length(title)")).reverse_order
281
    end
282 283
  end

284 285 286 287 288 289
  def test_reverse_arel_assoc_order_with_multiargument_function
    assert_nothing_raised do
      Topic.order(Arel.sql("REPLACE(title, '', '')") => :asc).reverse_order
    end
  end

290 291
  def test_reverse_order_with_nulls_first_or_last
    assert_raises(ActiveRecord::IrreversibleOrderError) do
292
      Topic.order(Arel.sql("title NULLS FIRST")).reverse_order
293 294
    end
    assert_raises(ActiveRecord::IrreversibleOrderError) do
295
      Topic.order(Arel.sql("title nulls last")).reverse_order
296 297 298 299 300 301 302 303 304
    end
  end

  def test_default_reverse_order_on_table_without_primary_key
    assert_raises(ActiveRecord::IrreversibleOrderError) do
      Edge.all.reverse_order
    end
  end

Y
Yves Senn 已提交
305
  def test_order_with_hash_and_symbol_generates_the_same_sql
306
    assert_equal Topic.order(:id).to_sql, Topic.order(id: :asc).to_sql
Y
Yves Senn 已提交
307 308
  end

309 310 311 312 313 314 315
  def test_finding_with_desc_order_with_string
    topics = Topic.order(id: "desc")
    assert_equal 5, topics.to_a.size
    assert_equal [topics(:fifth), topics(:fourth), topics(:third), topics(:second), topics(:first)], topics.to_a
  end

  def test_finding_with_asc_order_with_string
316
    topics = Topic.order(id: "asc")
317 318 319 320
    assert_equal 5, topics.to_a.size
    assert_equal [topics(:first), topics(:second), topics(:third), topics(:fourth), topics(:fifth)], topics.to_a
  end

321 322 323 324 325
  def test_support_upper_and_lower_case_directions
    assert_includes Topic.order(id: "ASC").to_sql, "ASC"
    assert_includes Topic.order(id: "asc").to_sql, "ASC"
    assert_includes Topic.order(id: :ASC).to_sql, "ASC"
    assert_includes Topic.order(id: :asc).to_sql, "ASC"
326

327 328 329
    assert_includes Topic.order(id: "DESC").to_sql, "DESC"
    assert_includes Topic.order(id: "desc").to_sql, "DESC"
    assert_includes Topic.order(id: :DESC).to_sql, "DESC"
330
    assert_includes Topic.order(id: :desc).to_sql, "DESC"
331 332
  end

333
  def test_raising_exception_on_invalid_hash_params
334 335
    e = assert_raise(ArgumentError) { Topic.order(:name, "id DESC", id: :asfsdf) }
    assert_equal 'Direction "asfsdf" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]', e.message
336
  end
337 338 339

  def test_finding_last_with_arel_order
    topics = Topic.order(Topic.arel_table[:id].asc)
340
    assert_equal topics(:fifth).title, topics.last.title
341 342
  end

343
  def test_finding_with_order_concatenated
344
    topics = Topic.order("author_name").order("title")
345
    assert_equal 5, topics.to_a.size
346 347 348
    assert_equal topics(:fourth).title, topics.first.title
  end

349 350 351 352 353 354 355 356 357 358 359 360
  def test_finding_with_order_by_aliased_attributes
    topics = Topic.order(:heading)
    assert_equal 5, topics.to_a.size
    assert_equal topics(:fifth).title, topics.first.title
  end

  def test_finding_with_assoc_order_by_aliased_attributes
    topics = Topic.order(heading: :desc)
    assert_equal 5, topics.to_a.size
    assert_equal topics(:third).title, topics.first.title
  end

S
Sebastian Martinez 已提交
361
  def test_finding_with_reorder
362
    topics = Topic.order("author_name").order("title").reorder("id").to_a
363
    topics_titles = topics.map(&:title)
364
    assert_equal ["The First Topic", "The Second Topic of the day", "The Third Topic of the day", "The Fourth Topic of the day", "The Fifth Topic of the day"], topics_titles
S
Sebastian Martinez 已提交
365
  end
366

367
  def test_finding_with_reorder_by_aliased_attributes
368
    topics = Topic.order("author_name").reorder(:heading)
369 370 371 372 373
    assert_equal 5, topics.to_a.size
    assert_equal topics(:fifth).title, topics.first.title
  end

  def test_finding_with_assoc_reorder_by_aliased_attributes
374
    topics = Topic.order("author_name").reorder(heading: :desc)
375 376
    assert_equal 5, topics.to_a.size
    assert_equal topics(:third).title, topics.first.title
S
Sebastian Martinez 已提交
377
  end
378

379
  def test_finding_with_order_and_take
380
    entrants = Entrant.order("id ASC").limit(2).to_a
381

P
Pratik Naik 已提交
382 383
    assert_equal 2, entrants.size
    assert_equal entrants(:first).name, entrants.first.name
384 385
  end

386
  def test_finding_with_cross_table_order_and_limit
387
    tags = Tag.includes(:taggings).
B
Ben Toews 已提交
388
              order("tags.name asc", "taggings.taggable_id asc", Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).
389
              limit(1).to_a
390 391 392
    assert_equal 1, tags.length
  end

393
  def test_finding_with_complex_order_and_limit
394
    tags = Tag.includes(:taggings).references(:taggings).order(Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).limit(1).to_a
395 396 397 398
    assert_equal 1, tags.length
  end

  def test_finding_with_complex_order
399
    tags = Tag.includes(:taggings).references(:taggings).order(Arel.sql("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)")).to_a
400
    assert_equal 3, tags.length
401 402
  end

403
  def test_finding_with_sanitized_order
B
Ben Toews 已提交
404
    query = Tag.order([Arel.sql("field(id, ?)"), [1, 3, 2]]).to_sql
405
    assert_match(/field\(id, 1,3,2\)/, query)
406

B
Ben Toews 已提交
407
    query = Tag.order([Arel.sql("field(id, ?)"), []]).to_sql
408 409
    assert_match(/field\(id, NULL\)/, query)

B
Ben Toews 已提交
410
    query = Tag.order([Arel.sql("field(id, ?)"), nil]).to_sql
411
    assert_match(/field\(id, NULL\)/, query)
412 413
  end

414
  def test_finding_with_order_limit_and_offset
415
    entrants = Entrant.order("id ASC").limit(2).offset(1)
416

417
    assert_equal 2, entrants.to_a.size
P
Pratik Naik 已提交
418
    assert_equal entrants(:second).name, entrants.first.name
419

420
    entrants = Entrant.order("id ASC").limit(2).offset(2)
421
    assert_equal 1, entrants.to_a.size
P
Pratik Naik 已提交
422
    assert_equal entrants(:third).name, entrants.first.name
423 424 425
  end

  def test_finding_with_group
426
    developers = Developer.group("salary").select("salary").to_a
427 428 429 430
    assert_equal 4, developers.size
    assert_equal 4, developers.map(&:salary).uniq.size
  end

431
  def test_select_with_block
432
    even_ids = Developer.all.select { |d| d.id % 2 == 0 }.map(&:id)
433
    assert_equal [2, 4, 6, 8, 10], even_ids.sort
434 435
  end

436 437 438 439
  def test_joins_with_nil_argument
    assert_nothing_raised { DependentFirm.joins(nil).first }
  end

440
  def test_finding_with_hash_conditions_on_joined_table
441
    firms = DependentFirm.joins(:account).where(name: "RailsCore", accounts: { credit_limit: 55..60 }).to_a
442 443 444 445 446
    assert_equal 1, firms.size
    assert_equal companies(:rails_core), firms.first
  end

  def test_find_all_with_join
447 448
    developers_on_project_one = Developer.joins("LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id").
      where("project_id=1").to_a
449 450

    assert_equal 3, developers_on_project_one.length
451
    developer_names = developers_on_project_one.map(&:name)
452 453
    assert_includes developer_names, "David"
    assert_includes developer_names, "Jamis"
454 455 456
  end

  def test_find_on_hash_conditions
457
    assert_equal Topic.all.merge!(where: { approved: false }).to_a, Topic.where(approved: false).to_a
458 459 460
  end

  def test_joins_with_string_array
461
    person_with_reader_and_post = Post.joins([
462 463 464 465 466 467
        "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
468

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
  def test_no_arguments_to_query_methods_raise_errors
    assert_raises(ArgumentError) { Topic.references() }
    assert_raises(ArgumentError) { Topic.includes() }
    assert_raises(ArgumentError) { Topic.preload() }
    assert_raises(ArgumentError) { Topic.group() }
    assert_raises(ArgumentError) { Topic.reorder() }
  end

  def test_blank_like_arguments_to_query_methods_dont_raise_errors
    assert_nothing_raised { Topic.references([]) }
    assert_nothing_raised { Topic.includes([]) }
    assert_nothing_raised { Topic.preload([]) }
    assert_nothing_raised { Topic.group([]) }
    assert_nothing_raised { Topic.reorder([]) }
  end

485
  def test_respond_to_delegates_to_arel
486
    relation = Topic.all
487
    fake_arel = Struct.new(:responds) {
488
      def respond_to?(method, access = false)
489 490 491 492 493 494 495 496 497 498 499
        responds << [method, access]
      end
    }.new []

    relation.extend(Module.new { attr_accessor :arel })
    relation.arel = fake_arel

    relation.respond_to?(:matching_attributes)
    assert_equal [:matching_attributes, false], fake_arel.responds.first
  end

500
  def test_respond_to_dynamic_finders
501
    relation = Topic.all
502

503
    ["find_by_title", "find_by_title_and_author_name"].each do |method|
504
      assert_respond_to relation, method, "Topic.all should respond to #{method.inspect}"
505 506
    end
  end
507

508
  def test_respond_to_class_methods_and_scopes
509
    assert Topic.all.respond_to?(:by_lifo)
510 511
  end

512
  def test_find_with_readonly_option
513 514
    Developer.all.each { |d| assert !d.readonly? }
    Developer.all.readonly.each { |d| assert d.readonly? }
515
  end
516 517

  def test_eager_association_loading_of_stis_with_multiple_references
518
    authors = Author.eager_load(posts: { special_comments: { post: [ :special_comments, :very_special_comment ] } }).
519
      order("comments.body, very_special_comments_posts.body").where("posts.id = 4").to_a
520

521 522 523 524 525 526 527
    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

528
  def test_find_with_preloaded_associations
529
    assert_queries(2) do
530
      posts = Post.preload(:comments).order("posts.id")
531
      assert posts.first.comments.first
532
    end
533

C
Carlos Antonio da Silva 已提交
534
    assert_queries(2) do
535
      posts = Post.preload(:comments).order("posts.id")
536
      assert posts.first.comments.first
537
    end
538

539
    assert_queries(2) do
540
      posts = Post.preload(:author).order("posts.id")
541
      assert posts.first.author
542
    end
543

C
Carlos Antonio da Silva 已提交
544
    assert_queries(2) do
545
      posts = Post.preload(:author).order("posts.id")
546 547 548
      assert posts.first.author
    end

C
Carlos Antonio da Silva 已提交
549
    assert_queries(3) do
550
      posts = Post.preload(:author, :comments).order("posts.id")
551
      assert posts.first.author
552 553 554 555
      assert posts.first.comments.first
    end
  end

556 557 558 559 560 561 562
  def test_preload_applies_to_all_chained_preloaded_scopes
    assert_queries(3) do
      post = Post.with_comments.with_tags.first
      assert post
    end
  end

563 564
  def test_find_with_included_associations
    assert_queries(2) do
565
      posts = Post.includes(:comments).order("posts.id")
566 567 568
      assert posts.first.comments.first
    end

C
Carlos Antonio da Silva 已提交
569
    assert_queries(2) do
570
      posts = Post.all.includes(:comments).order("posts.id")
571 572 573 574
      assert posts.first.comments.first
    end

    assert_queries(2) do
575
      posts = Post.includes(:author).order("posts.id")
576 577 578
      assert posts.first.author
    end

C
Carlos Antonio da Silva 已提交
579
    assert_queries(3) do
580
      posts = Post.includes(:author, :comments).order("posts.id")
581
      assert posts.first.author
582
      assert posts.first.comments.first
583 584
    end
  end
585

586
  def test_default_scoping_finder_methods
587 588
    developers = DeveloperCalledDavid.order("id").map(&:id).sort
    assert_equal Developer.where(name: "David").map(&:id).sort, developers
589 590
  end

591
  def test_includes_with_select
592
    query = Post.select("comments_count AS ranking").order("ranking").includes(:comments)
593 594
      .where(comments: { id: 1 })

595
    assert_equal ["comments_count AS ranking"], query.select_values
596 597 598
    assert_equal 1, query.to_a.size
  end

599
  def test_preloading_with_associations_and_merges
600
    post = Post.create! title: "Uhuu", body: "body"
601
    reader = Reader.create! post_id: post.id, person_id: 1
602
    comment = Comment.create! post_id: post.id, body: "body"
603 604 605

    assert !comment.respond_to?(:readers)

606
    post_rel = Post.preload(:readers).joins(:readers).where(title: "Uhuu")
607 608 609 610 611 612 613 614
    result_comment = Comment.joins(:post).merge(post_rel).to_a.first
    assert_equal comment, result_comment

    assert_no_queries do
      assert_equal post, result_comment.post
      assert_equal [reader], result_comment.post.readers.to_a
    end

615
    post_rel = Post.includes(:readers).where(title: "Uhuu")
616 617 618 619 620 621 622 623 624
    result_comment = Comment.joins(:post).merge(post_rel).first
    assert_equal comment, result_comment

    assert_no_queries do
      assert_equal post, result_comment.post
      assert_equal [reader], result_comment.post.readers.to_a
    end
  end

625
  def test_preloading_with_associations_default_scopes_and_merges
626
    post = Post.create! title: "Uhuu", body: "body"
627 628
    reader = Reader.create! post_id: post.id, person_id: 1

629
    post_rel = PostWithPreloadDefaultScope.preload(:readers).joins(:readers).where(title: "Uhuu")
630 631 632 633 634 635
    result_post = PostWithPreloadDefaultScope.all.merge(post_rel).to_a.first

    assert_no_queries do
      assert_equal [reader], result_post.readers.to_a
    end

636
    post_rel = PostWithIncludesDefaultScope.includes(:readers).where(title: "Uhuu")
637 638 639 640 641 642 643
    result_post = PostWithIncludesDefaultScope.all.merge(post_rel).to_a.first

    assert_no_queries do
      assert_equal [reader], result_post.readers.to_a
    end
  end

644 645
  def test_loading_with_one_association
    posts = Post.preload(:comments)
646 647
    post = posts.find { |p| p.id == 1 }
    assert_equal 2, post.comments.size
648
    assert_includes post.comments, comments(:greetings)
649

650
    post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
651
    assert_equal 2, post.comments.size
652
    assert_includes post.comments, comments(:greetings)
653

654
    posts = Post.preload(:last_comment)
655 656 657 658
    post = posts.find { |p| p.id == 1 }
    assert_equal Post.find(1).last_comment, post.last_comment
  end

659 660
  def test_to_sql_on_eager_join
    expected = assert_sql {
661
      Post.eager_load(:last_comment).order("comments.id DESC").to_a
662
    }.first
663
    actual = Post.eager_load(:last_comment).order("comments.id DESC").to_sql
664 665 666
    assert_equal expected, actual
  end

667 668 669 670 671 672
  def test_to_sql_on_scoped_proxy
    auth = Author.first
    Post.where("1=1").written_by(auth)
    assert_not auth.posts.to_sql.include?("1=1")
  end

673
  def test_loading_with_one_association_with_non_preload
674
    posts = Post.eager_load(:last_comment).order("comments.id DESC")
675 676 677
    post = posts.find { |p| p.id == 1 }
    assert_equal Post.find(1).last_comment, post.last_comment
  end
678 679 680 681 682 683 684

  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
685
      assert_equal expected_taggings, author.taggings.uniq.sort_by(&:id)
686 687
    end

688
    authors = Author.all
689 690 691 692 693
    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
694
    author = Author.all.find_by_id!(authors(:david).id)
695 696
    assert_equal "David", author.name

697
    assert_raises(ActiveRecord::RecordNotFound) { Author.all.find_by_id_and_name!(20, "invalid") }
698 699
  end

P
Pratik Naik 已提交
700
  def test_find_id
701
    authors = Author.all
P
Pratik Naik 已提交
702 703

    david = authors.find(authors(:david).id)
704
    assert_equal "David", david.name
P
Pratik Naik 已提交
705

706
    assert_raises(ActiveRecord::RecordNotFound) { authors.where(name: "lifo").find("42") }
P
Pratik Naik 已提交
707
  end
708

P
Pratik Naik 已提交
709
  def test_find_ids
710
    authors = Author.order("id ASC")
P
Pratik Naik 已提交
711 712 713 714

    results = authors.find(authors(:david).id, authors(:mary).id)
    assert_kind_of Array, results
    assert_equal 2, results.size
715 716
    assert_equal "David", results[0].name
    assert_equal "Mary", results[1].name
P
Pratik Naik 已提交
717 718
    assert_equal results, authors.find([authors(:david).id, authors(:mary).id])

719
    assert_raises(ActiveRecord::RecordNotFound) { authors.where(name: "lifo").find(authors(:david).id, "42") }
720
    assert_raises(ActiveRecord::RecordNotFound) { authors.find(["42", 43]) }
P
Pratik Naik 已提交
721 722
  end

723
  def test_find_in_empty_array
724
    authors = Author.all.where(id: [])
725
    assert authors.to_a.blank?
726 727
  end

728 729
  def test_where_with_ar_object
    author = Author.first
730
    authors = Author.all.where(id: author)
731
    assert_equal 1, authors.to_a.length
732 733
  end

734 735
  def test_find_with_list_of_ar
    author = Author.first
736
    authors = Author.find([author.id])
737 738 739 740 741 742 743 744 745
    assert_equal author, authors.first
  end

  def test_find_by_id_with_list_of_ar
    author = Author.first
    authors = Author.find_by_id([author])
    assert_equal author, authors
  end

746 747 748
  def test_find_all_using_where_twice_should_or_the_relation
    david = authors(:david)
    relation = Author.unscoped
749 750 751
    relation = relation.where(name: david.name)
    relation = relation.where(name: "Santiago")
    relation = relation.where(id: david.id)
752
    assert_equal [], relation.to_a
753 754
  end

A
Aaron Patterson 已提交
755 756 757
  def test_multi_where_ands_queries
    relation = Author.unscoped
    david = authors(:david)
758
    sql = relation.where(name: david.name).where(name: "Santiago").to_sql
759
    assert_match("AND", sql)
A
Aaron Patterson 已提交
760 761 762
  end

  def test_find_all_with_multiple_should_use_and
A
Aaron Patterson 已提交
763 764
    david = authors(:david)
    relation = [
765 766 767
      { name: david.name },
      { name: "Santiago" },
      { name: "tenderlove" },
A
Aaron Patterson 已提交
768 769 770
    ].inject(Author.unscoped) do |memo, param|
      memo.where(param)
    end
771
    assert_equal [], relation.to_a
A
Aaron Patterson 已提交
772
  end
A
Aaron Patterson 已提交
773

774 775 776 777 778 779 780
  def test_typecasting_where_with_array
    ids = Author.pluck(:id)
    slugs = ids.map { |id| "#{id}-as-a-slug" }

    assert_equal Author.all.to_a, Author.where(id: slugs).to_a
  end

781 782 783
  def test_find_all_using_where_with_relation
    david = authors(:david)
    assert_queries(1) {
784
      relation = Author.where(id: Author.where(id: david.id))
785
      assert_equal [david], relation.to_a
786
    }
787 788

    assert_queries(1) {
789
      relation = Author.where("id in (?)", Author.where(id: david).select(:id))
790 791
      assert_equal [david], relation.to_a
    }
792 793

    assert_queries(1) do
794
      relation = Author.where("id in (:author_ids)", author_ids: Author.where(id: david).select(:id))
795 796 797 798 799 800
      assert_equal [david], relation.to_a
    end
  end

  def test_find_all_using_where_with_relation_with_bound_values
    david = authors(:david)
801
    davids_posts = david.posts.order(:id).to_a
802 803 804

    assert_queries(1) do
      relation = Post.where(id: david.posts.select(:id))
805
      assert_equal davids_posts, relation.order(:id).to_a
806 807 808
    end

    assert_queries(1) do
809 810
      relation = Post.where("id in (?)", david.posts.select(:id))
      assert_equal davids_posts, relation.order(:id).to_a, "should process Relation as bind variables"
811 812 813
    end

    assert_queries(1) do
814 815
      relation = Post.where("id in (:post_ids)", post_ids: david.posts.select(:id))
      assert_equal davids_posts, relation.order(:id).to_a, "should process Relation as named bind variables"
816
    end
817 818
  end

819 820 821
  def test_find_all_using_where_with_relation_and_alternate_primary_key
    cool_first = minivans(:cool_first)
    assert_queries(1) {
822
      relation = Minivan.where(minivan_id: Minivan.where(name: cool_first.name))
823
      assert_equal [cool_first], relation.to_a
824 825 826
    }
  end

827 828 829
  def test_find_all_using_where_with_relation_does_not_alter_select_values
    david = authors(:david)

830
    subquery = Author.where(id: david.id)
831 832

    assert_queries(1) {
833
      relation = Author.where(id: subquery)
834
      assert_equal [david], relation.to_a
835 836 837 838 839
    }

    assert_equal 0, subquery.select_values.size
  end

840 841 842
  def test_find_all_using_where_with_relation_with_joins
    david = authors(:david)
    assert_queries(1) {
843
      relation = Author.where(id: Author.joins(:posts).where(id: david.id))
844
      assert_equal [david], relation.to_a
845 846 847 848 849 850
    }
  end

  def test_find_all_using_where_with_relation_with_select_to_build_subquery
    david = authors(:david)
    assert_queries(1) {
851
      relation = Author.where(name: Author.where(id: david.id).select(:name))
852
      assert_equal [david], relation.to_a
853
    }
A
Aaron Patterson 已提交
854 855
  end

856
  def test_last
857
    authors = Author.all
858
    assert_equal authors(:bob), authors.last
859 860
  end

P
Pratik Naik 已提交
861
  def test_destroy_all
862
    davids = Author.where(name: "David")
P
Pratik Naik 已提交
863 864 865 866 867

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

868
    assert_difference("Author.count", -1) { davids.destroy_all }
P
Pratik Naik 已提交
869 870 871 872 873

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

P
Pratik Naik 已提交
874
  def test_delete_all
875
    davids = Author.where(name: "David")
P
Pratik Naik 已提交
876

877
    assert_difference("Author.count", -1) { davids.delete_all }
P
Pratik Naik 已提交
878 879 880 881
    assert ! davids.loaded?
  end

  def test_delete_all_loaded
882
    davids = Author.where(name: "David")
P
Pratik Naik 已提交
883 884 885 886 887

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

888
    assert_difference("Author.count", -1) { davids.delete_all }
P
Pratik Naik 已提交
889 890 891 892 893

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

894
  def test_delete_all_with_unpermitted_relation_raises_error
895
    assert_raises(ActiveRecord::ActiveRecordError) { Author.distinct.delete_all }
896
    assert_raises(ActiveRecord::ActiveRecordError) { Author.group(:name).delete_all }
897
    assert_raises(ActiveRecord::ActiveRecordError) { Author.having("SUM(id) < 3").delete_all }
898 899
  end

900 901
  def test_select_with_aggregates
    posts = Post.select(:title, :body)
R
Rafael Mendonça França 已提交
902

903 904 905 906
    assert_equal 11, posts.count(:all)
    assert_equal 11, posts.size
    assert posts.any?
    assert posts.many?
R
Rafael Mendonça França 已提交
907
    assert_not posts.empty?
908
  end
R
Rafael Mendonça França 已提交
909

910 911 912 913 914 915 916 917
  def test_select_takes_a_variable_list_of_args
    david = developers(:david)

    developer = Developer.where(id: david.id).select(:name, :salary).first
    assert_equal david.name, developer.name
    assert_equal david.salary, developer.salary
  end

918 919 920 921 922 923 924
  def test_select_takes_an_aliased_attribute
    first = topics(:first)

    topic = Topic.where(id: first.id).select(:heading).first
    assert_equal first.heading, topic.heading
  end

925 926 927 928
  def test_select_argument_error
    assert_raises(ArgumentError) { Developer.select }
  end

P
Pratik Naik 已提交
929
  def test_count
930
    posts = Post.all
P
Pratik Naik 已提交
931

932 933 934
    assert_equal 11, posts.count
    assert_equal 11, posts.count(:all)
    assert_equal 11, posts.count(:id)
P
Pratik Naik 已提交
935

936 937
    assert_equal 3, posts.where("comments_count > 1").count
    assert_equal 6, posts.where(comments_count: 0).count
P
Pratik Naik 已提交
938 939
  end

940 941
  def test_count_with_block
    posts = Post.all
942
    assert_equal 8, posts.count { |p| p.comments_count.even? }
943 944
  end

945 946 947 948 949 950 951 952 953 954 955
  def test_count_on_association_relation
    author = Author.last
    another_author = Author.first
    posts = Post.where(author_id: author.id)

    assert_equal author.posts.where(author_id: author.id).size, posts.count

    assert_equal 0, author.posts.where(author_id: another_author.id).size
    assert author.posts.where(author_id: another_author.id).empty?
  end

P
Pratik Naik 已提交
956
  def test_count_with_distinct
957
    posts = Post.all
P
Pratik Naik 已提交
958

959
    assert_equal 4, posts.distinct(true).count(:comments_count)
960
    assert_equal 11, posts.distinct(false).count(:comments_count)
P
Pratik Naik 已提交
961

962
    assert_equal 4, posts.distinct(true).select(:comments_count).count
963
    assert_equal 11, posts.distinct(false).select(:comments_count).count
P
Pratik Naik 已提交
964 965
  end

966 967 968 969 970 971
  def test_size_with_distinct
    posts = Post.distinct.select(:author_id, :comments_count)
    assert_queries(1) { assert_equal 8, posts.size }
    assert_queries(1) { assert_equal 8, posts.load.size }
  end

972 973 974 975 976
  def test_update_all_with_scope
    tag = Tag.first
    Post.tagged_with(tag.id).update_all title: "rofl"
    list = Post.tagged_with(tag.id).all.to_a
    assert_operator list.length, :>, 0
977
    list.each { |post| assert_equal "rofl", post.title }
978 979
  end

P
Pratik Naik 已提交
980
  def test_count_explicit_columns
981
    Post.update_all(comments_count: nil)
982
    posts = Post.all
P
Pratik Naik 已提交
983

984 985
    assert_equal [0], posts.select("comments_count").where("id is not null").group("id").order("id").count.values.uniq
    assert_equal 0, posts.where("id is not null").select("comments_count").count
986

987 988
    assert_equal 11, posts.select("comments_count").count("id")
    assert_equal 0, posts.select("comments_count").count
P
Pratik Naik 已提交
989
    assert_equal 0, posts.count(:comments_count)
990
    assert_equal 0, posts.count("comments_count")
P
Pratik Naik 已提交
991
  end
992

993
  def test_multiple_selects
994
    post = Post.all.select("comments_count").select("title").order("id ASC").first
995 996 997 998
    assert_equal "Welcome to the weblog", post.title
    assert_equal 2, post.comments_count
  end

999
  def test_size
1000
    posts = Post.all
1001

1002
    assert_queries(1) { assert_equal 11, posts.size }
1003 1004
    assert ! posts.loaded?

1005
    best_posts = posts.where(comments_count: 0)
1006
    best_posts.load # force load
1007
    assert_no_queries { assert_equal 6, best_posts.size }
1008 1009
  end

1010
  def test_size_with_limit
1011
    posts = Post.limit(10)
1012

1013
    assert_queries(1) { assert_equal 10, posts.size }
1014 1015
    assert ! posts.loaded?

1016
    best_posts = posts.where(comments_count: 0)
1017
    best_posts.load # force load
1018
    assert_no_queries { assert_equal 6, best_posts.size }
1019 1020 1021 1022 1023 1024 1025 1026
  end

  def test_size_with_zero_limit
    posts = Post.limit(0)

    assert_no_queries { assert_equal 0, posts.size }
    assert ! posts.loaded?

1027
    posts.load # force load
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
    assert_no_queries { assert_equal 0, posts.size }
  end

  def test_empty_with_zero_limit
    posts = Post.limit(0)

    assert_no_queries { assert_equal true, posts.empty? }
    assert ! posts.loaded?
  end

1038
  def test_count_complex_chained_relations
1039
    posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
1040

1041
    expected = { 1 => 4, 2 => 1 }
1042 1043 1044
    assert_equal expected, posts.count
  end

1045
  def test_empty
1046
    posts = Post.all
1047 1048 1049 1050

    assert_queries(1) { assert_equal false, posts.empty? }
    assert ! posts.loaded?

1051
    no_posts = posts.where(title: "")
1052 1053 1054
    assert_queries(1) { assert_equal true, no_posts.empty? }
    assert ! no_posts.loaded?

1055
    best_posts = posts.where(comments_count: 0)
1056
    best_posts.load # force load
1057 1058 1059 1060 1061
    assert_no_queries { assert_equal false, best_posts.empty? }
  end

  def test_empty_complex_chained_relations
    posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
A
Andrew White 已提交
1062

1063 1064 1065
    assert_queries(1) { assert_equal false, posts.empty? }
    assert ! posts.loaded?

1066
    no_posts = posts.where(title: "")
1067 1068 1069 1070
    assert_queries(1) { assert_equal true, no_posts.empty? }
    assert ! no_posts.loaded?
  end

P
Pratik Naik 已提交
1071
  def test_any
1072
    posts = Post.all
P
Pratik Naik 已提交
1073

1074 1075 1076 1077 1078 1079
    # This test was failing when run on its own (as opposed to running the entire suite).
    # The second line in the assert_queries block was causing visit_Arel_Attributes_Attribute
    # in Arel::Visitors::ToSql to trigger a SHOW TABLES query. Running that line here causes
    # the SHOW TABLES result to be cached so we don't have to do it again in the block.
    #
    # This is obviously a rubbish fix but it's the best I can come up with for now...
1080
    posts.where(id: nil).any?
1081

P
Pratik Naik 已提交
1082 1083
    assert_queries(3) do
      assert posts.any? # Uses COUNT()
1084
      assert ! posts.where(id: nil).any?
P
Pratik Naik 已提交
1085

1086 1087
      assert posts.any? { |p| p.id > 0 }
      assert ! posts.any? { |p| p.id <= 0 }
P
Pratik Naik 已提交
1088 1089 1090 1091 1092 1093
    end

    assert posts.loaded?
  end

  def test_many
1094
    posts = Post.all
1095

P
Pratik Naik 已提交
1096 1097
    assert_queries(2) do
      assert posts.many? # Uses COUNT()
1098 1099
      assert posts.many? { |p| p.id > 0 }
      assert ! posts.many? { |p| p.id < 2 }
P
Pratik Naik 已提交
1100
    end
1101

P
Pratik Naik 已提交
1102 1103 1104
    assert posts.loaded?
  end

1105
  def test_many_with_limits
1106
    posts = Post.all
1107 1108 1109 1110

    assert posts.many?
    assert ! posts.limit(1).many?
  end
P
Pratik Naik 已提交
1111

1112 1113 1114 1115 1116 1117 1118 1119 1120
  def test_none?
    posts = Post.all
    assert_queries(1) do
      assert ! posts.none? # Uses COUNT()
    end

    assert ! posts.loaded?

    assert_queries(1) do
1121 1122
      assert posts.none? { |p| p.id < 0 }
      assert ! posts.none? { |p| p.id == 1 }
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
    end

    assert posts.loaded?
  end

  def test_one
    posts = Post.all
    assert_queries(1) do
      assert ! posts.one? # Uses COUNT()
    end

    assert ! posts.loaded?

    assert_queries(1) do
1137 1138
      assert ! posts.one? { |p| p.id < 3 }
      assert posts.one? { |p| p.id == 1 }
1139 1140 1141 1142 1143
    end

    assert posts.loaded?
  end

1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
  def test_to_a_should_dup_target
    posts = Post.all

    original_size = posts.size
    removed = posts.to_a.pop

    assert_equal original_size, posts.size
    assert_includes posts.to_a, removed
  end

P
Pratik Naik 已提交
1154
  def test_build
1155
    posts = Post.all
P
Pratik Naik 已提交
1156 1157 1158 1159 1160 1161

    post = posts.new
    assert_kind_of Post, post
  end

  def test_scoped_build
1162
    posts = Post.where(title: "You told a lie")
P
Pratik Naik 已提交
1163 1164 1165

    post = posts.new
    assert_kind_of Post, post
1166
    assert_equal "You told a lie", post.title
P
Pratik Naik 已提交
1167 1168
  end

1169
  def test_create
1170
    birds = Bird.all
1171 1172 1173

    sparrow = birds.create
    assert_kind_of Bird, sparrow
1174
    assert !sparrow.persisted?
1175

1176
    hen = birds.where(name: "hen").create
1177
    assert hen.persisted?
1178
    assert_equal "hen", hen.name
1179 1180 1181
  end

  def test_create_bang
1182
    birds = Bird.all
1183 1184 1185

    assert_raises(ActiveRecord::RecordInvalid) { birds.create! }

1186
    hen = birds.where(name: "hen").create!
1187
    assert_kind_of Bird, hen
1188
    assert hen.persisted?
1189
    assert_equal "hen", hen.name
1190
  end
P
Pratik Naik 已提交
1191

1192 1193 1194 1195 1196 1197 1198 1199 1200
  def test_create_with_polymorphic_association
    author = authors(:david)
    post = posts(:welcome)
    comment = Comment.where(post: post, author: author).create!(body: "hello")

    assert_equal author, comment.author
    assert_equal post, comment.post
  end

1201
  def test_first_or_create
1202
    parrot = Bird.where(color: "green").first_or_create(name: "parrot")
1203 1204
    assert_kind_of Bird, parrot
    assert parrot.persisted?
1205 1206
    assert_equal "parrot", parrot.name
    assert_equal "green", parrot.color
1207

1208
    same_parrot = Bird.where(color: "green").first_or_create(name: "parakeet")
1209 1210 1211 1212 1213 1214
    assert_kind_of Bird, same_parrot
    assert same_parrot.persisted?
    assert_equal parrot, same_parrot
  end

  def test_first_or_create_with_no_parameters
1215
    parrot = Bird.where(color: "green").first_or_create
1216 1217
    assert_kind_of Bird, parrot
    assert !parrot.persisted?
1218
    assert_equal "green", parrot.color
1219 1220 1221
  end

  def test_first_or_create_with_block
1222
    parrot = Bird.where(color: "green").first_or_create { |bird| bird.name = "parrot" }
1223 1224
    assert_kind_of Bird, parrot
    assert parrot.persisted?
1225 1226
    assert_equal "green", parrot.color
    assert_equal "parrot", parrot.name
1227

1228
    same_parrot = Bird.where(color: "green").first_or_create { |bird| bird.name = "parakeet" }
1229 1230 1231 1232
    assert_equal parrot, same_parrot
  end

  def test_first_or_create_with_array
1233
    several_green_birds = Bird.where(color: "green").first_or_create([{ name: "parrot" }, { name: "parakeet" }])
1234 1235 1236
    assert_kind_of Array, several_green_birds
    several_green_birds.each { |bird| assert bird.persisted? }

1237
    same_parrot = Bird.where(color: "green").first_or_create([{ name: "hummingbird" }, { name: "macaw" }])
1238 1239 1240 1241 1242
    assert_kind_of Bird, same_parrot
    assert_equal several_green_birds.first, same_parrot
  end

  def test_first_or_create_bang_with_valid_options
1243
    parrot = Bird.where(color: "green").first_or_create!(name: "parrot")
1244 1245
    assert_kind_of Bird, parrot
    assert parrot.persisted?
1246 1247
    assert_equal "parrot", parrot.name
    assert_equal "green", parrot.color
1248

1249
    same_parrot = Bird.where(color: "green").first_or_create!(name: "parakeet")
1250 1251 1252 1253 1254 1255
    assert_kind_of Bird, same_parrot
    assert same_parrot.persisted?
    assert_equal parrot, same_parrot
  end

  def test_first_or_create_bang_with_invalid_options
1256
    assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create!(pirate_id: 1) }
1257 1258 1259
  end

  def test_first_or_create_bang_with_no_parameters
1260
    assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create! }
1261 1262 1263
  end

  def test_first_or_create_bang_with_valid_block
1264
    parrot = Bird.where(color: "green").first_or_create! { |bird| bird.name = "parrot" }
1265 1266
    assert_kind_of Bird, parrot
    assert parrot.persisted?
1267 1268
    assert_equal "green", parrot.color
    assert_equal "parrot", parrot.name
1269

1270
    same_parrot = Bird.where(color: "green").first_or_create! { |bird| bird.name = "parakeet" }
1271 1272 1273 1274 1275
    assert_equal parrot, same_parrot
  end

  def test_first_or_create_bang_with_invalid_block
    assert_raise(ActiveRecord::RecordInvalid) do
1276
      Bird.where(color: "green").first_or_create! { |bird| bird.pirate_id = 1 }
1277 1278 1279 1280
    end
  end

  def test_first_or_create_with_valid_array
1281
    several_green_birds = Bird.where(color: "green").first_or_create!([{ name: "parrot" }, { name: "parakeet" }])
1282 1283 1284
    assert_kind_of Array, several_green_birds
    several_green_birds.each { |bird| assert bird.persisted? }

1285
    same_parrot = Bird.where(color: "green").first_or_create!([{ name: "hummingbird" }, { name: "macaw" }])
1286 1287 1288 1289 1290
    assert_kind_of Bird, same_parrot
    assert_equal several_green_birds.first, same_parrot
  end

  def test_first_or_create_with_invalid_array
1291
    assert_raises(ActiveRecord::RecordInvalid) { Bird.where(color: "green").first_or_create!([ { name: "parrot" }, { pirate_id: 1 } ]) }
1292 1293
  end

1294
  def test_first_or_initialize
1295
    parrot = Bird.where(color: "green").first_or_initialize(name: "parrot")
1296 1297 1298 1299
    assert_kind_of Bird, parrot
    assert !parrot.persisted?
    assert parrot.valid?
    assert parrot.new_record?
1300 1301
    assert_equal "parrot", parrot.name
    assert_equal "green", parrot.color
1302 1303
  end

1304
  def test_first_or_initialize_with_no_parameters
1305
    parrot = Bird.where(color: "green").first_or_initialize
1306 1307 1308 1309
    assert_kind_of Bird, parrot
    assert !parrot.persisted?
    assert !parrot.valid?
    assert parrot.new_record?
1310
    assert_equal "green", parrot.color
1311 1312
  end

1313
  def test_first_or_initialize_with_block
1314
    parrot = Bird.where(color: "green").first_or_initialize { |bird| bird.name = "parrot" }
1315 1316 1317 1318
    assert_kind_of Bird, parrot
    assert !parrot.persisted?
    assert parrot.valid?
    assert parrot.new_record?
1319 1320
    assert_equal "green", parrot.color
    assert_equal "parrot", parrot.name
1321 1322
  end

1323
  def test_find_or_create_by
1324
    assert_nil Bird.find_by(name: "bob")
1325

1326
    bird = Bird.find_or_create_by(name: "bob")
1327 1328
    assert bird.persisted?

1329
    assert_equal bird, Bird.find_or_create_by(name: "bob")
1330 1331
  end

1332
  def test_find_or_create_by_with_create_with
1333
    assert_nil Bird.find_by(name: "bob")
1334

1335
    bird = Bird.create_with(color: "green").find_or_create_by(name: "bob")
1336
    assert bird.persisted?
1337
    assert_equal "green", bird.color
1338

1339
    assert_equal bird, Bird.create_with(color: "blue").find_or_create_by(name: "bob")
1340 1341
  end

1342
  def test_find_or_create_by!
1343
    assert_raises(ActiveRecord::RecordInvalid) { Bird.find_or_create_by!(color: "green") }
1344 1345 1346
  end

  def test_find_or_initialize_by
1347
    assert_nil Bird.find_by(name: "bob")
1348

1349
    bird = Bird.find_or_initialize_by(name: "bob")
1350 1351 1352
    assert bird.new_record?
    bird.save!

1353
    assert_equal bird, Bird.find_or_initialize_by(name: "bob")
1354 1355
  end

1356
  def test_explicit_create_with
1357
    hens = Bird.where(name: "hen")
1358
    assert_equal "hen", hens.new.name
1359

1360
    hens = hens.create_with(name: "cock")
1361
    assert_equal "cock", hens.new.name
1362 1363
  end

P
Pratik Naik 已提交
1364
  def test_except
1365
    relation = Post.where(author_id: 1).order("id ASC").limit(1)
1366
    assert_equal [posts(:welcome)], relation.to_a
P
Pratik Naik 已提交
1367 1368

    author_posts = relation.except(:order, :limit)
1369
    assert_equal Post.where(author_id: 1).to_a, author_posts.to_a
P
Pratik Naik 已提交
1370 1371

    all_posts = relation.except(:where, :order, :limit)
J
Jon Leighton 已提交
1372
    assert_equal Post.all, all_posts
P
Pratik Naik 已提交
1373 1374
  end

E
Emilio Tagua 已提交
1375
  def test_only
1376
    relation = Post.where(author_id: 1).order("id ASC").limit(1)
1377
    assert_equal [posts(:welcome)], relation.to_a
E
Emilio Tagua 已提交
1378 1379

    author_posts = relation.only(:where)
1380
    assert_equal Post.where(author_id: 1).to_a, author_posts.to_a
E
Emilio Tagua 已提交
1381 1382

    all_posts = relation.only(:limit)
M
Matthew Draper 已提交
1383
    assert_equal Post.limit(1).to_a, all_posts.to_a
E
Emilio Tagua 已提交
1384 1385
  end

P
Pratik Naik 已提交
1386
  def test_anonymous_extension
1387
    relation = Post.where(author_id: 1).order("id ASC").extending do
P
Pratik Naik 已提交
1388
      def author
1389
        "lifo"
P
Pratik Naik 已提交
1390 1391 1392 1393 1394 1395 1396 1397
      end
    end

    assert_equal "lifo", relation.author
    assert_equal "lifo", relation.limit(1).author
  end

  def test_named_extension
1398
    relation = Post.where(author_id: 1).order("id ASC").extending(Post::NamedExtension)
P
Pratik Naik 已提交
1399 1400 1401
    assert_equal "lifo", relation.author
    assert_equal "lifo", relation.limit(1).author
  end
1402 1403

  def test_order_by_relation_attribute
1404
    assert_equal Post.order(Post.arel_table[:title]).to_a, Post.order("title").to_a
1405
  end
1406

1407
  def test_default_scope_order_with_scope_order
1408 1409
    assert_equal "zyke", CoolCar.order_using_new_style.limit(1).first.name
    assert_equal "zyke", FastCar.order_using_new_style.limit(1).first.name
1410 1411 1412
  end

  def test_order_using_scoping
1413 1414
    car1 = CoolCar.order("id DESC").scoping do
      CoolCar.all.merge!(order: "id asc").first
1415
    end
1416
    assert_equal "zyke", car1.name
1417

1418 1419
    car2 = FastCar.order("id DESC").scoping do
      FastCar.all.merge!(order: "id asc").first
1420
    end
1421
    assert_equal "zyke", car2.name
1422 1423 1424
  end

  def test_unscoped_block_style
1425 1426
    assert_equal "honda", CoolCar.unscoped { CoolCar.order_using_new_style.limit(1).first.name }
    assert_equal "honda", FastCar.unscoped { FastCar.order_using_new_style.limit(1).first.name }
1427 1428
  end

1429
  def test_intersection_with_array
1430
    relation = Author.where(name: "David")
1431
    rails_author = relation.first
1432

1433 1434 1435
    assert_equal [rails_author], [rails_author] & relation
    assert_equal [rails_author], relation & [rails_author]
  end
1436

1437
  def test_primary_key
1438
    assert_equal "id", Post.all.primary_key
1439
  end
1440

1441
  def test_ordering_with_extra_spaces
1442
    assert_equal authors(:david), Author.order("id DESC , name DESC").last
1443
  end
1444

1445 1446 1447 1448
  def test_update_all_with_blank_argument
    assert_raises(ArgumentError) { Comment.update_all({}) }
  end

1449
  def test_update_all_with_joins
1450
    comments = Comment.joins(:post).where("posts.id" => posts(:welcome).id)
1451 1452
    count    = comments.count

1453
    assert_equal count, comments.update_all(post_id: posts(:thinking).id)
1454 1455
    assert_equal posts(:thinking), comments(:greetings).post
  end
1456 1457

  def test_update_all_with_joins_and_limit
1458
    comments = Comment.joins(:post).where("posts.id" => posts(:welcome).id).limit(1)
1459
    assert_equal 1, comments.update_all(post_id: posts(:thinking).id)
1460 1461 1462
  end

  def test_update_all_with_joins_and_limit_and_order
1463
    comments = Comment.joins(:post).where("posts.id" => posts(:welcome).id).order("comments.id").limit(1)
1464
    assert_equal 1, comments.update_all(post_id: posts(:thinking).id)
1465 1466 1467 1468 1469
    assert_equal posts(:thinking), comments(:greetings).post
    assert_equal posts(:welcome),  comments(:more_greetings).post
  end

  def test_update_all_with_joins_and_offset
1470
    all_comments = Comment.joins(:post).where("posts.id" => posts(:welcome).id)
1471 1472 1473
    count        = all_comments.count
    comments     = all_comments.offset(1)

1474
    assert_equal count - 1, comments.update_all(post_id: posts(:thinking).id)
1475 1476 1477
  end

  def test_update_all_with_joins_and_offset_and_order
1478
    all_comments = Comment.joins(:post).where("posts.id" => posts(:welcome).id).order("posts.id", "comments.id")
1479 1480 1481
    count        = all_comments.count
    comments     = all_comments.offset(1)

1482
    assert_equal count - 1, comments.update_all(post_id: posts(:thinking).id)
1483 1484 1485
    assert_equal posts(:thinking), comments(:more_greetings).post
    assert_equal posts(:welcome),  comments(:greetings).post
  end
1486

1487
  def test_update_on_relation
1488 1489
    topic1 = TopicWithCallbacks.create! title: "arel", author_name: nil
    topic2 = TopicWithCallbacks.create! title: "activerecord", author_name: nil
1490
    topics = TopicWithCallbacks.where(id: [topic1.id, topic2.id])
1491
    topics.update(title: "adequaterecord")
1492

1493 1494
    assert_equal "adequaterecord", topic1.reload.title
    assert_equal "adequaterecord", topic2.reload.title
1495
    # Testing that the before_update callbacks have run
1496 1497
    assert_equal "David", topic1.reload.author_name
    assert_equal "David", topic2.reload.author_name
1498 1499
  end

R
Ryuta Kamizono 已提交
1500
  def test_update_on_relation_passing_active_record_object_is_not_permitted
1501
    topic = Topic.create!(title: "Foo", author_name: nil)
1502
    assert_raises(ArgumentError) do
1503
      Topic.where(id: topic.id).update(topic, title: "Bar")
1504 1505 1506
    end
  end

1507
  def test_distinct
1508 1509
    tag1 = Tag.create(name: "Foo")
    tag2 = Tag.create(name: "Foo")
1510

1511
    query = Tag.select(:name).where(id: [tag1.id, tag2.id])
1512

1513
    assert_equal ["Foo", "Foo"], query.map(&:name)
1514
    assert_sql(/DISTINCT/) do
1515
      assert_equal ["Foo"], query.distinct.map(&:name)
1516 1517
    end
    assert_sql(/DISTINCT/) do
1518
      assert_equal ["Foo"], query.distinct(true).map(&:name)
1519
    end
1520
    assert_equal ["Foo", "Foo"], query.distinct(true).distinct(false).map(&:name)
1521
  end
1522

1523
  def test_doesnt_add_having_values_if_options_are_blank
1524
    scope = Post.having("")
1525
    assert scope.having_clause.empty?
1526 1527

    scope = Post.having([])
1528 1529 1530 1531 1532
    assert scope.having_clause.empty?
  end

  def test_having_with_binds_for_both_where_and_having
    post = Post.first
1533 1534
    having_then_where = Post.having(id: post.id).where(title: post.title).group(:id)
    where_then_having = Post.where(title: post.title).having(id: post.id).group(:id)
1535 1536 1537 1538 1539 1540 1541

    assert_equal [post], having_then_where
    assert_equal [post], where_then_having
  end

  def test_multiple_where_and_having_clauses
    post = Post.first
1542 1543
    having_then_where = Post.having(id: post.id).where(title: post.title)
      .having(id: post.id).where(title: post.title).group(:id)
1544 1545

    assert_equal [post], having_then_where
1546 1547
  end

1548 1549 1550 1551
  def test_grouping_by_column_with_reserved_name
    assert_equal [], Possession.select(:where).group(:where).to_a
  end

1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
  def test_references_triggers_eager_loading
    scope = Post.includes(:comments)
    assert !scope.eager_loading?
    assert scope.references(:comments).eager_loading?
  end

  def test_references_doesnt_trigger_eager_loading_if_reference_not_included
    scope = Post.references(:comments)
    assert !scope.eager_loading?
  end
1562

1563
  def test_automatically_added_where_references
1564
    scope = Post.where(comments: { body: "Bla" })
1565
    assert_equal ["comments"], scope.references_values
1566

1567 1568
    scope = Post.where("comments.body" => "Bla")
    assert_equal ["comments"], scope.references_values
1569
  end
1570

1571 1572
  def test_automatically_added_where_not_references
    scope = Post.where.not(comments: { body: "Bla" })
1573
    assert_equal ["comments"], scope.references_values
1574

1575 1576
    scope = Post.where.not("comments.body" => "Bla")
    assert_equal ["comments"], scope.references_values
1577 1578
  end

1579
  def test_automatically_added_having_references
1580
    scope = Post.having(comments: { body: "Bla" })
1581
    assert_equal ["comments"], scope.references_values
1582

1583 1584
    scope = Post.having("comments.body" => "Bla")
    assert_equal ["comments"], scope.references_values
1585
  end
1586 1587

  def test_automatically_added_order_references
1588 1589
    scope = Post.order("comments.body")
    assert_equal ["comments"], scope.references_values
1590

1591
    scope = Post.order(Arel.sql("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}"))
1592 1593 1594 1595 1596
    if current_adapter?(:OracleAdapter)
      assert_equal ["COMMENTS"], scope.references_values
    else
      assert_equal ["comments"], scope.references_values
    end
1597

1598 1599
    scope = Post.order("comments.body", "yaks.body")
    assert_equal ["comments", "yaks"], scope.references_values
1600 1601

    # Don't infer yaks, let's not go down that road again...
1602 1603
    scope = Post.order("comments.body, yaks.body")
    assert_equal ["comments"], scope.references_values
1604

1605 1606
    scope = Post.order("comments.body asc")
    assert_equal ["comments"], scope.references_values
1607

1608
    scope = Post.order(Arel.sql("foo(comments.body)"))
1609 1610
    assert_equal [], scope.references_values
  end
1611

1612
  def test_automatically_added_reorder_references
1613
    scope = Post.reorder("comments.body")
1614 1615
    assert_equal %w(comments), scope.references_values

1616
    scope = Post.reorder(Arel.sql("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}"))
1617 1618 1619 1620 1621
    if current_adapter?(:OracleAdapter)
      assert_equal ["COMMENTS"], scope.references_values
    else
      assert_equal ["comments"], scope.references_values
    end
1622

1623
    scope = Post.reorder("comments.body", "yaks.body")
1624 1625 1626
    assert_equal %w(comments yaks), scope.references_values

    # Don't infer yaks, let's not go down that road again...
1627
    scope = Post.reorder("comments.body, yaks.body")
1628 1629
    assert_equal %w(comments), scope.references_values

1630
    scope = Post.reorder("comments.body asc")
1631 1632
    assert_equal %w(comments), scope.references_values

1633
    scope = Post.reorder(Arel.sql("foo(comments.body)"))
1634 1635 1636
    assert_equal [], scope.references_values
  end

1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
  def test_order_with_reorder_nil_removes_the_order
    relation = Post.order(:title).reorder(nil)

    assert_nil relation.order_values.first
  end

  def test_reverse_order_with_reorder_nil_removes_the_order
    relation = Post.order(:title).reverse_order.reorder(nil)

    assert_nil relation.order_values.first
  end

1649
  def test_presence
1650
    topics = Topic.all
1651

1652
    # the first query is triggered because there are no topics yet.
1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666
    assert_queries(1) { assert topics.present? }

    # checking if there are topics is used before you actually display them,
    # thus it shouldn't invoke an extra count query.
    assert_no_queries { assert topics.present? }
    assert_no_queries { assert !topics.blank? }

    # shows count of topics and loops after loading the query should not trigger extra queries either.
    assert_no_queries { topics.size }
    assert_no_queries { topics.length }
    assert_no_queries { topics.each }

    # count always trigger the COUNT query.
    assert_queries(1) { topics.count }
1667 1668 1669

    assert topics.loaded?
  end
1670 1671 1672 1673 1674 1675 1676 1677 1678 1679

  test "find_by with hash conditions returns the first matching record" do
    assert_equal posts(:eager_other), Post.order(:id).find_by(author_id: 2)
  end

  test "find_by with non-hash conditions returns the first matching record" do
    assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = 2")
  end

  test "find_by with multi-arg conditions returns the first matching record" do
1680
    assert_equal posts(:eager_other), Post.order(:id).find_by("author_id = ?", 2)
1681 1682 1683
  end

  test "find_by returns nil if the record is missing" do
1684
    assert_nil Post.all.find_by("1 = 0")
1685 1686
  end

1687
  test "find_by doesn't have implicit ordering" do
1688
    assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by(author_id: 2) }
1689 1690
  end

1691 1692 1693 1694
  test "find_by requires at least one argument" do
    assert_raises(ArgumentError) { Post.all.find_by }
  end

1695 1696 1697 1698 1699 1700 1701 1702 1703
  test "find_by! with hash conditions returns the first matching record" do
    assert_equal posts(:eager_other), Post.order(:id).find_by!(author_id: 2)
  end

  test "find_by! with non-hash conditions returns the first matching record" do
    assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = 2")
  end

  test "find_by! with multi-arg conditions returns the first matching record" do
1704
    assert_equal posts(:eager_other), Post.order(:id).find_by!("author_id = ?", 2)
1705 1706
  end

1707
  test "find_by! doesn't have implicit ordering" do
1708
    assert_sql(/^((?!ORDER).)*$/) { Post.all.find_by!(author_id: 2) }
1709 1710
  end

1711 1712
  test "find_by! raises RecordNotFound if the record is missing" do
    assert_raises(ActiveRecord::RecordNotFound) do
1713
      Post.all.find_by!("1 = 0")
1714 1715
    end
  end
1716

1717 1718 1719 1720
  test "find_by! requires at least one argument" do
    assert_raises(ArgumentError) { Post.all.find_by! }
  end

1721
  test "loaded relations cannot be mutated by multi value methods" do
1722
    relation = Post.all
1723 1724 1725
    relation.to_a

    assert_raises(ActiveRecord::ImmutableRelation) do
1726
      relation.where! "foo"
1727 1728 1729 1730
    end
  end

  test "loaded relations cannot be mutated by single value methods" do
1731
    relation = Post.all
1732 1733 1734 1735 1736 1737 1738 1739
    relation.to_a

    assert_raises(ActiveRecord::ImmutableRelation) do
      relation.limit! 5
    end
  end

  test "loaded relations cannot be mutated by merge!" do
1740
    relation = Post.all
1741 1742 1743
    relation.to_a

    assert_raises(ActiveRecord::ImmutableRelation) do
1744
      relation.merge! where: "foo"
1745 1746
    end
  end
1747

1748 1749 1750 1751 1752 1753 1754 1755 1756
  test "loaded relations cannot be mutated by extending!" do
    relation = Post.all
    relation.to_a

    assert_raises(ActiveRecord::ImmutableRelation) do
      relation.extending! Module.new
    end
  end

1757 1758
  test "relations with cached arel can't be mutated [internal API]" do
    relation = Post.all
1759
    relation.arel
1760 1761 1762 1763 1764

    assert_raises(ActiveRecord::ImmutableRelation) { relation.limit!(5) }
    assert_raises(ActiveRecord::ImmutableRelation) { relation.where!("1 = 2") }
  end

1765 1766 1767 1768
  test "relations show the records in #inspect" do
    relation = Post.limit(2)
    assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect
  end
1769

1770
  test "relations limit the records in #inspect at 10" do
1771 1772 1773
    relation = Post.limit(11)
    assert_equal "#<ActiveRecord::Relation [#{Post.limit(10).map(&:inspect).join(', ')}, ...]>", relation.inspect
  end
1774

1775
  test "relations don't load all records in #inspect" do
1776
    assert_sql(/LIMIT|ROWNUM <=|FETCH FIRST/) do
1777 1778 1779 1780
      Post.all.inspect
    end
  end

1781 1782 1783 1784 1785 1786 1787 1788 1789 1790
  test "already-loaded relations don't perform a new query in #inspect" do
    relation = Post.limit(2)
    relation.to_a

    expected = "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>"

    assert_no_queries do
      assert_equal expected, relation.inspect
    end
  end
1791

1792
  test "using a custom table affects the wheres" do
1793
    post = posts(:welcome)
1794

1795 1796
    assert_equal post, custom_post_relation.where!(title: post.title).take
  end
1797

1798
  test "using a custom table with joins affects the joins" do
R
Ryuta Kamizono 已提交
1799 1800
    post = posts(:welcome)

1801
    assert_equal post, custom_post_relation.joins(:author).where!(title: post.title).take
1802
  end
J
Jon Leighton 已提交
1803

1804
  test "arel_attribute respects a custom table" do
1805
    assert_equal [posts(:sti_comments)], custom_post_relation.ranked_by_comments.limit_by(1).to_a
1806 1807
  end

1808 1809 1810 1811
  test "alias_tracker respects a custom table" do
    assert_equal posts(:welcome), custom_post_relation("categories_posts").joins(:categories).first
  end

1812
  test "#load" do
J
Jon Leighton 已提交
1813 1814 1815 1816 1817 1818
    relation = Post.all
    assert_queries(1) do
      assert_equal relation, relation.load
    end
    assert_no_queries { relation.to_a }
  end
1819

1820 1821 1822
  test "group with select and includes" do
    authors_count = Post.select("author_id, COUNT(author_id) AS num_posts").
      group("author_id").order("author_id").includes(:author).to_a
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832

    assert_no_queries do
      result = authors_count.map do |post|
        [post.num_posts, post.author.try(:name)]
      end

      expected = [[1, nil], [5, "David"], [3, "Mary"], [2, "Bob"]]
      assert_equal expected, result
    end
  end
1833

1834 1835 1836 1837 1838 1839
  test "joins with select" do
    posts = Post.joins(:author).select("id", "authors.author_address_id").order("posts.id").limit(3)
    assert_equal [1, 2, 4], posts.map(&:id)
    assert_equal [1, 1, 1], posts.map(&:author_address_id)
  end

1840 1841 1842 1843 1844 1845
  test "delegations do not leak to other classes" do
    Topic.all.by_lifo
    assert Topic.all.class.method_defined?(:by_lifo)
    assert !Post.all.respond_to?(:by_lifo)
  end

R
Ryuta Kamizono 已提交
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
  def test_unscope_with_subquery
    p1 = Post.where(id: 1)
    p2 = Post.where(id: 2)

    assert_not_equal p1, p2

    comments = Comment.where(post: p1).unscope(where: :post_id).where(post: p2)

    assert_not_equal p1.first.comments, comments
    assert_equal p2.first.comments, comments
  end

1858 1859 1860 1861 1862 1863 1864 1865
  def test_unscope_specific_where_value
    posts = Post.where(title: "Welcome to the weblog", body: "Such a lovely day")

    assert_equal 1, posts.count
    assert_equal 1, posts.unscope(where: :title).count
    assert_equal 1, posts.unscope(where: :body).count
  end

1866
  def test_locked_should_not_build_arel
1867
    posts = Post.locked
1868 1869 1870 1871
    assert posts.locked?
    assert_nothing_raised { posts.lock!(false) }
  end

1872
  def test_relation_join_method
1873
    assert_equal "Thank you for the welcome,Thank you again for the welcome", Post.first.comments.join(",")
1874
  end
1875

1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916
  test "#skip_query_cache!" do
    Post.cache do
      assert_queries(1) do
        Post.all.load
        Post.all.load
      end

      assert_queries(2) do
        Post.all.skip_query_cache!.load
        Post.all.skip_query_cache!.load
      end
    end
  end

  test "#skip_query_cache! with an eager load" do
    Post.cache do
      assert_queries(1) do
        Post.eager_load(:comments).load
        Post.eager_load(:comments).load
      end

      assert_queries(2) do
        Post.eager_load(:comments).skip_query_cache!.load
        Post.eager_load(:comments).skip_query_cache!.load
      end
    end
  end

  test "#skip_query_cache! with a preload" do
    Post.cache do
      assert_queries(2) do
        Post.preload(:comments).load
        Post.preload(:comments).load
      end

      assert_queries(4) do
        Post.preload(:comments).skip_query_cache!.load
        Post.preload(:comments).skip_query_cache!.load
      end
    end
  end
1917

1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930
  test "#where with set" do
    david = authors(:david)
    mary = authors(:mary)

    authors = Author.where(name: ["David", "Mary"].to_set)
    assert_equal [david, mary], authors
  end

  test "#where with empty set" do
    authors = Author.where(name: Set.new)
    assert_empty authors
  end

1931
  private
1932 1933
    def custom_post_relation(alias_name = "omg_posts")
      table_alias = Post.arel_table.alias(alias_name)
1934 1935 1936
      table_metadata = ActiveRecord::TableMetadata.new(Post, table_alias)
      predicate_builder = ActiveRecord::PredicateBuilder.new(table_metadata)

1937 1938 1939 1940 1941
      ActiveRecord::Relation.create(
        Post,
        table: table_alias,
        predicate_builder: predicate_builder
      )
1942
    end
P
Pratik Naik 已提交
1943
end