ibm_db 2.5.27-x86-mingw32 → 2.6.0-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +5 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +264 -264
  8. data/ext/extconf_MacOS.rb +269 -0
  9. data/ext/ibm_db.c +1 -1
  10. data/ext/ruby_ibm_db.h +241 -241
  11. data/init.rb +41 -41
  12. data/lib/IBM_DB.rb +27 -3
  13. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3290 -3290
  14. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  15. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  16. data/lib/mswin32/ibm_db.rb +104 -20
  17. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  18. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  19. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  20. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  21. data/test/cases/adapter_test.rb +207 -207
  22. data/test/cases/associations/belongs_to_associations_test.rb +711 -711
  23. data/test/cases/associations/cascaded_eager_loading_test.rb +181 -181
  24. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +851 -851
  25. data/test/cases/associations/join_model_test.rb +743 -743
  26. data/test/cases/attribute_methods_test.rb +822 -822
  27. data/test/cases/base_test.rb +2133 -2133
  28. data/test/cases/calculations_test.rb +482 -482
  29. data/test/cases/migration_test.rb +2408 -2408
  30. data/test/cases/persistence_test.rb +642 -642
  31. data/test/cases/query_cache_test.rb +257 -257
  32. data/test/cases/relations_test.rb +1182 -1182
  33. data/test/cases/schema_dumper_test.rb +256 -256
  34. data/test/cases/transaction_callbacks_test.rb +300 -300
  35. data/test/cases/validations/uniqueness_validation_test.rb +299 -299
  36. data/test/cases/xml_serialization_test.rb +408 -408
  37. data/test/config.yml +154 -154
  38. data/test/connections/native_ibm_db/connection.rb +43 -43
  39. data/test/ibm_db_test.rb +24 -24
  40. data/test/models/warehouse_thing.rb +4 -4
  41. data/test/schema/schema.rb +751 -751
  42. metadata +31 -16
@@ -1,1182 +1,1182 @@
1
- require "cases/helper"
2
- require 'models/tag'
3
- require 'models/tagging'
4
- require 'models/post'
5
- require 'models/topic'
6
- require 'models/comment'
7
- require 'models/reply'
8
- require 'models/author'
9
- require 'models/comment'
10
- require 'models/entrant'
11
- require 'models/developer'
12
- require 'models/company'
13
- require 'models/bird'
14
- require 'models/car'
15
- require 'models/engine'
16
- require 'models/tyre'
17
- require 'models/minivan'
18
-
19
-
20
- class RelationTest < ActiveRecord::TestCase
21
- fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
22
- :tags, :taggings, :cars, :minivans
23
-
24
- def test_do_not_double_quote_string_id
25
- van = Minivan.last
26
- assert van
27
- assert_equal van.id, Minivan.where(:minivan_id => van).to_a.first.minivan_id
28
- end
29
-
30
- def test_do_not_double_quote_string_id_with_array
31
- van = Minivan.last
32
- assert van
33
- assert_equal van, Minivan.where(:minivan_id => [van]).to_a.first
34
- end
35
-
36
- def test_bind_values
37
- relation = Post.scoped
38
- assert_equal [], relation.bind_values
39
-
40
- relation2 = relation.bind 'foo'
41
- assert_equal %w{ foo }, relation2.bind_values
42
- assert_equal [], relation.bind_values
43
- end
44
-
45
- def test_two_scopes_with_includes_should_not_drop_any_include
46
- car = Car.incl_engines.incl_tyres.first
47
- assert_no_queries { car.tyres.length }
48
- assert_no_queries { car.engines.length }
49
- end
50
-
51
- def test_dynamic_finder
52
- x = Post.where('author_id = ?', 1)
53
- assert x.klass.respond_to?(:find_by_id), '@klass should handle dynamic finders'
54
- end
55
-
56
- def test_multivalue_where
57
- posts = Post.where('author_id = ? AND id = ?', 1, 1)
58
- assert_equal 1, posts.to_a.size
59
- end
60
-
61
- def test_scoped
62
- topics = Topic.scoped
63
- assert_kind_of ActiveRecord::Relation, topics
64
- assert_equal 4, topics.size
65
- end
66
-
67
- def test_to_json
68
- assert_nothing_raised { Bird.scoped.to_json }
69
- assert_nothing_raised { Bird.scoped.all.to_json }
70
- end
71
-
72
- def test_to_yaml
73
- assert_nothing_raised { Bird.scoped.to_yaml }
74
- assert_nothing_raised { Bird.scoped.all.to_yaml }
75
- end
76
-
77
- def test_to_xml
78
- assert_nothing_raised { Bird.scoped.to_xml }
79
- assert_nothing_raised { Bird.scoped.all.to_xml }
80
- end
81
-
82
- def test_scoped_all
83
- topics = Topic.scoped.all
84
- assert_kind_of Array, topics
85
- assert_no_queries { assert_equal 4, topics.size }
86
- end
87
-
88
- def test_loaded_all
89
- topics = Topic.scoped
90
-
91
- assert_queries(1) do
92
- 2.times { assert_equal 4, topics.all.size }
93
- end
94
-
95
- assert topics.loaded?
96
- end
97
-
98
- def test_scoped_first
99
- topics = Topic.scoped.order('id ASC')
100
-
101
- assert_queries(1) do
102
- 2.times { assert_equal "The First Topic", topics.first.title }
103
- end
104
-
105
- assert ! topics.loaded?
106
- end
107
-
108
- def test_loaded_first
109
- topics = Topic.scoped.order('id ASC')
110
-
111
- assert_queries(1) do
112
- topics.all # force load
113
- 2.times { assert_equal "The First Topic", topics.first.title }
114
- end
115
-
116
- assert topics.loaded?
117
- end
118
-
119
- def test_reload
120
- topics = Topic.scoped
121
-
122
- assert_queries(1) do
123
- 2.times { topics.to_a }
124
- end
125
-
126
- assert topics.loaded?
127
-
128
- original_size = topics.to_a.size
129
- Topic.create! :title => 'fake'
130
-
131
- assert_queries(1) { topics.reload }
132
- assert_equal original_size + 1, topics.size
133
- assert topics.loaded?
134
- end
135
-
136
- def test_finding_with_conditions
137
- assert_equal ["David"], Author.where(:name => 'David').map(&:name)
138
- assert_equal ['Mary'], Author.where(["name = ?", 'Mary']).map(&:name)
139
- assert_equal ['Mary'], Author.where("name = ?", 'Mary').map(&:name)
140
- end
141
-
142
- def test_finding_with_order
143
- topics = Topic.order('id')
144
- assert_equal 4, topics.to_a.size
145
- assert_equal topics(:first).title, topics.first.title
146
- end
147
-
148
-
149
- def test_finding_with_arel_order
150
- topics = Topic.order(Topic.arel_table[:id].asc)
151
- assert_equal 4, topics.to_a.size
152
- assert_equal topics(:first).title, topics.first.title
153
- end
154
-
155
- def test_finding_last_with_arel_order
156
- topics = Topic.order(Topic.arel_table[:id].asc)
157
- assert_equal topics(:fourth).title, topics.last.title
158
- end
159
-
160
- def test_finding_with_order_concatenated
161
- topics = Topic.order('author_name').order('title')
162
- assert_equal 4, topics.to_a.size
163
- assert_equal topics(:fourth).title, topics.first.title
164
- end
165
-
166
- def test_finding_with_reorder
167
- topics = Topic.order('author_name').order('title').reorder('id').all
168
- topics_titles = topics.map{ |t| t.title }
169
- assert_equal ['The First Topic', 'The Second Topic of the day', 'The Third Topic of the day', 'The Fourth Topic of the day'], topics_titles
170
- end
171
-
172
- def test_finding_with_order_and_take
173
- entrants = Entrant.order("id ASC").limit(2).to_a
174
-
175
- assert_equal 2, entrants.size
176
- assert_equal entrants(:first).name, entrants.first.name
177
- end
178
-
179
- def test_finding_with_cross_table_order_and_limit
180
- tags = Tag.includes(:taggings).
181
- order("tags.name asc", "taggings.taggable_id asc", "REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").
182
- limit(1).to_a
183
- assert_equal 1, tags.length
184
- end
185
-
186
- def test_finding_with_complex_order_and_limit
187
- tags = Tag.includes(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").limit(1).to_a
188
- assert_equal 1, tags.length
189
- end
190
-
191
- def test_finding_with_complex_order
192
- tags = Tag.includes(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a
193
- assert_equal 3, tags.length
194
- end
195
-
196
- def test_finding_with_order_limit_and_offset
197
- entrants = Entrant.order("id ASC").limit(2).offset(1)
198
-
199
- assert_equal 2, entrants.to_a.size
200
- assert_equal entrants(:second).name, entrants.first.name
201
-
202
- entrants = Entrant.order("id ASC").limit(2).offset(2)
203
- assert_equal 1, entrants.to_a.size
204
- assert_equal entrants(:third).name, entrants.first.name
205
- end
206
-
207
- def test_finding_with_group
208
- developers = Developer.group("salary").select("salary").to_a
209
- assert_equal 4, developers.size
210
- assert_equal 4, developers.map(&:salary).uniq.size
211
- end
212
-
213
- def test_select_with_block
214
- even_ids = Developer.scoped.select {|d| d.id % 2 == 0 }.map(&:id)
215
- assert_equal [2, 4, 6, 8, 10], even_ids.sort
216
- end
217
-
218
- def test_joins_with_nil_argument
219
- assert_nothing_raised { DependentFirm.joins(nil).first }
220
- end
221
-
222
- def test_finding_with_hash_conditions_on_joined_table
223
- firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a
224
- assert_equal 1, firms.size
225
- assert_equal companies(:rails_core), firms.first
226
- end
227
-
228
- def test_find_all_with_join
229
- developers_on_project_one = Developer.joins('LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id').
230
- where('project_id=1').to_a
231
-
232
- assert_equal 3, developers_on_project_one.length
233
- developer_names = developers_on_project_one.map { |d| d.name }
234
- assert developer_names.include?('David')
235
- assert developer_names.include?('Jamis')
236
- end
237
-
238
- def test_find_on_hash_conditions
239
- assert_equal Topic.find(:all, :conditions => {:approved => false}), Topic.where({ :approved => false }).to_a
240
- end
241
-
242
- def test_joins_with_string_array
243
- person_with_reader_and_post = Post.joins([
244
- "INNER JOIN categorizations ON categorizations.post_id = posts.id",
245
- "INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
246
- ]
247
- ).to_a
248
- assert_equal 1, person_with_reader_and_post.size
249
- end
250
-
251
- def test_scoped_responds_to_delegated_methods
252
- relation = Topic.scoped
253
-
254
- ["map", "uniq", "sort", "insert", "delete", "update"].each do |method|
255
- assert_respond_to relation, method, "Topic.scoped should respond to #{method.inspect}"
256
- end
257
- end
258
-
259
- def test_respond_to_delegates_to_relation
260
- relation = Topic.scoped
261
- fake_arel = Struct.new(:responds) {
262
- def respond_to? method, access = false
263
- responds << [method, access]
264
- end
265
- }.new []
266
-
267
- relation.extend(Module.new { attr_accessor :arel })
268
- relation.arel = fake_arel
269
-
270
- relation.respond_to?(:matching_attributes)
271
- assert_equal [:matching_attributes, false], fake_arel.responds.first
272
-
273
- fake_arel.responds = []
274
- relation.respond_to?(:matching_attributes, true)
275
- assert_equal [:matching_attributes, true], fake_arel.responds.first
276
- end
277
-
278
- def test_respond_to_dynamic_finders
279
- relation = Topic.scoped
280
-
281
- ["find_by_title", "find_by_title_and_author_name", "find_or_create_by_title", "find_or_initialize_by_title_and_author_name"].each do |method|
282
- assert_respond_to relation, method, "Topic.scoped should respond to #{method.inspect}"
283
- end
284
- end
285
-
286
- def test_respond_to_class_methods_and_scopes
287
- assert DeveloperOrderedBySalary.scoped.respond_to?(:all_ordered_by_name)
288
- assert Topic.scoped.respond_to?(:by_lifo)
289
- end
290
-
291
- def test_find_with_readonly_option
292
- Developer.scoped.each { |d| assert !d.readonly? }
293
- Developer.scoped.readonly.each { |d| assert d.readonly? }
294
- end
295
-
296
- def test_eager_association_loading_of_stis_with_multiple_references
297
- authors = Author.eager_load(:posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } }).
298
- order('comments.body, very_special_comments_posts.body').where('posts.id = 4').to_a
299
-
300
- assert_equal [authors(:david)], authors
301
- assert_no_queries do
302
- authors.first.posts.first.special_comments.first.post.special_comments
303
- authors.first.posts.first.special_comments.first.post.very_special_comment
304
- end
305
- end
306
-
307
- def test_find_with_preloaded_associations
308
- assert_queries(2) do
309
- posts = Post.preload(:comments).order('posts.id')
310
- assert posts.first.comments.first
311
- end
312
-
313
- assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
314
- posts = Post.preload(:comments).order('posts.id')
315
- assert posts.first.comments.first
316
- end
317
-
318
- assert_queries(2) do
319
- posts = Post.preload(:author).order('posts.id')
320
- assert posts.first.author
321
- end
322
-
323
- assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
324
- posts = Post.preload(:author).order('posts.id')
325
- assert posts.first.author
326
- end
327
-
328
- assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 3) do
329
- posts = Post.preload(:author, :comments).order('posts.id')
330
- assert posts.first.author
331
- assert posts.first.comments.first
332
- end
333
- end
334
-
335
- def test_find_with_included_associations
336
- assert_queries(2) do
337
- posts = Post.includes(:comments).order('posts.id')
338
- assert posts.first.comments.first
339
- end
340
-
341
- assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
342
- posts = Post.scoped.includes(:comments).order('posts.id')
343
- assert posts.first.comments.first
344
- end
345
-
346
- assert_queries(2) do
347
- posts = Post.includes(:author).order('posts.id')
348
- assert posts.first.author
349
- end
350
-
351
- assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 3) do
352
- posts = Post.includes(:author, :comments).order('posts.id')
353
- assert posts.first.author
354
- assert posts.first.comments.first
355
- end
356
- end
357
-
358
- def test_default_scope_with_conditions_string
359
- assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeveloperCalledDavid.scoped.map(&:id).sort
360
- assert_nil DeveloperCalledDavid.create!.name
361
- end
362
-
363
- def test_default_scope_with_conditions_hash
364
- assert_equal Developer.find_all_by_name('Jamis').map(&:id).sort, DeveloperCalledJamis.scoped.map(&:id).sort
365
- assert_equal 'Jamis', DeveloperCalledJamis.create!.name
366
- end
367
-
368
- def test_default_scoping_finder_methods
369
- developers = DeveloperCalledDavid.order('id').map(&:id).sort
370
- assert_equal Developer.find_all_by_name('David').map(&:id).sort, developers
371
- end
372
-
373
- def test_loading_with_one_association
374
- posts = Post.preload(:comments)
375
- post = posts.find { |p| p.id == 1 }
376
- assert_equal 2, post.comments.size
377
- assert post.comments.include?(comments(:greetings))
378
-
379
- post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
380
- assert_equal 2, post.comments.size
381
- assert post.comments.include?(comments(:greetings))
382
-
383
- posts = Post.preload(:last_comment)
384
- post = posts.find { |p| p.id == 1 }
385
- assert_equal Post.find(1).last_comment, post.last_comment
386
- end
387
-
388
- def test_loading_with_one_association_with_non_preload
389
- posts = Post.eager_load(:last_comment).order('comments.id DESC')
390
- post = posts.find { |p| p.id == 1 }
391
- assert_equal Post.find(1).last_comment, post.last_comment
392
- end
393
-
394
- def test_dynamic_find_by_attributes_should_yield_found_object
395
- david = authors(:david)
396
- yielded_value = nil
397
- Author.find_by_name(david.name) do |author|
398
- yielded_value = author
399
- end
400
- assert_equal david, yielded_value
401
- end
402
-
403
- def test_dynamic_find_by_attributes
404
- david = authors(:david)
405
- author = Author.preload(:taggings).find_by_id(david.id)
406
- expected_taggings = taggings(:welcome_general, :thinking_general)
407
-
408
- assert_no_queries do
409
- assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
410
- end
411
-
412
- authors = Author.scoped
413
- assert_equal david, authors.find_by_id_and_name(david.id, david.name)
414
- assert_equal david, authors.find_by_id_and_name!(david.id, david.name)
415
- end
416
-
417
- def test_dynamic_find_by_attributes_bang
418
- author = Author.scoped.find_by_id!(authors(:david).id)
419
- assert_equal "David", author.name
420
-
421
- assert_raises(ActiveRecord::RecordNotFound) { Author.scoped.find_by_id_and_name!(20, 'invalid') }
422
- end
423
-
424
- def test_dynamic_find_all_by_attributes
425
- authors = Author.scoped
426
-
427
- davids = authors.find_all_by_name('David')
428
- assert_kind_of Array, davids
429
- assert_equal [authors(:david)], davids
430
- end
431
-
432
- def test_dynamic_find_or_initialize_by_attributes
433
- authors = Author.scoped
434
-
435
- lifo = authors.find_or_initialize_by_name('Lifo')
436
- assert_equal "Lifo", lifo.name
437
- assert !lifo.persisted?
438
-
439
- assert_equal authors(:david), authors.find_or_initialize_by_name(:name => 'David')
440
- end
441
-
442
- def test_dynamic_find_or_create_by_attributes
443
- authors = Author.scoped
444
-
445
- lifo = authors.find_or_create_by_name('Lifo')
446
- assert_equal "Lifo", lifo.name
447
- assert lifo.persisted?
448
-
449
- assert_equal authors(:david), authors.find_or_create_by_name(:name => 'David')
450
- end
451
-
452
- def test_dynamic_find_or_create_by_attributes_bang
453
- authors = Author.scoped
454
-
455
- assert_raises(ActiveRecord::RecordInvalid) { authors.find_or_create_by_name!('') }
456
-
457
- lifo = authors.find_or_create_by_name!('Lifo')
458
- assert_equal "Lifo", lifo.name
459
- assert lifo.persisted?
460
-
461
- assert_equal authors(:david), authors.find_or_create_by_name!(:name => 'David')
462
- end
463
-
464
- def test_find_id
465
- authors = Author.scoped
466
-
467
- david = authors.find(authors(:david).id)
468
- assert_equal 'David', david.name
469
-
470
- assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') }
471
- end
472
-
473
- def test_find_ids
474
- authors = Author.order('id ASC')
475
-
476
- results = authors.find(authors(:david).id, authors(:mary).id)
477
- assert_kind_of Array, results
478
- assert_equal 2, results.size
479
- assert_equal 'David', results[0].name
480
- assert_equal 'Mary', results[1].name
481
- assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
482
-
483
- assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') }
484
- assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) }
485
- end
486
-
487
- def test_find_in_empty_array
488
- authors = Author.scoped.where(:id => [])
489
- assert_blank authors.all
490
- end
491
-
492
- def test_where_with_ar_object
493
- author = Author.first
494
- authors = Author.scoped.where(:id => author)
495
- assert_equal 1, authors.all.length
496
- end
497
-
498
- def test_find_with_list_of_ar
499
- author = Author.first
500
- authors = Author.find([author])
501
- assert_equal author, authors.first
502
- end
503
-
504
- class Mary < Author; end
505
-
506
- def test_find_by_classname
507
- Author.create!(:name => Mary.name)
508
- assert_equal 1, Author.where(:name => Mary).size
509
- end
510
-
511
- def test_find_by_id_with_list_of_ar
512
- author = Author.first
513
- authors = Author.find_by_id([author])
514
- assert_equal author, authors
515
- end
516
-
517
- def test_find_all_using_where_twice_should_or_the_relation
518
- david = authors(:david)
519
- relation = Author.unscoped
520
- relation = relation.where(:name => david.name)
521
- relation = relation.where(:name => 'Santiago')
522
- relation = relation.where(:id => david.id)
523
- assert_equal [], relation.all
524
- end
525
-
526
- def test_multi_where_ands_queries
527
- relation = Author.unscoped
528
- david = authors(:david)
529
- sql = relation.where(:name => david.name).where(:name => 'Santiago').to_sql
530
- assert_match('AND', sql)
531
- end
532
-
533
- def test_find_all_with_multiple_should_use_and
534
- david = authors(:david)
535
- relation = [
536
- { :name => david.name },
537
- { :name => 'Santiago' },
538
- { :name => 'tenderlove' },
539
- ].inject(Author.unscoped) do |memo, param|
540
- memo.where(param)
541
- end
542
- assert_equal [], relation.all
543
- end
544
-
545
- def test_find_all_using_where_with_relation
546
- david = authors(:david)
547
- # switching the lines below would succeed in current rails
548
- # assert_queries(2) {
549
- assert_queries(1) {
550
- relation = Author.where(:id => Author.where(:id => david.id))
551
- assert_equal [david], relation.all
552
- }
553
- end
554
-
555
- def test_find_all_using_where_with_relation_and_alternate_primary_key
556
- cool_first = minivans(:cool_first)
557
- # switching the lines below would succeed in current rails
558
- # assert_queries(2) {
559
- assert_queries(1) {
560
- relation = Minivan.where(:minivan_id => Minivan.where(:name => cool_first.name))
561
- assert_equal [cool_first], relation.all
562
- }
563
- end
564
-
565
- def test_find_all_using_where_with_relation_does_not_alter_select_values
566
- david = authors(:david)
567
-
568
- subquery = Author.where(:id => david.id)
569
-
570
- assert_queries(1) {
571
- relation = Author.where(:id => subquery)
572
- assert_equal [david], relation.all
573
- }
574
-
575
- assert_equal 0, subquery.select_values.size
576
- end
577
-
578
- def test_find_all_using_where_with_relation_with_joins
579
- david = authors(:david)
580
- assert_queries(1) {
581
- relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
582
- assert_equal [david], relation.all
583
- }
584
- end
585
-
586
-
587
- def test_find_all_using_where_with_relation_with_select_to_build_subquery
588
- david = authors(:david)
589
- assert_queries(1) {
590
- relation = Author.where(:name => Author.where(:id => david.id).select(:name))
591
- assert_equal [david], relation.all
592
- }
593
- end
594
-
595
- def test_exists
596
- davids = Author.where(:name => 'David')
597
- assert davids.exists?
598
- assert davids.exists?(authors(:david).id)
599
- assert ! davids.exists?(authors(:mary).id)
600
- assert ! davids.exists?("42")
601
- assert ! davids.exists?(42)
602
-
603
- fake = Author.where(:name => 'fake author')
604
- assert ! fake.exists?
605
- assert ! fake.exists?(authors(:david).id)
606
- end
607
-
608
- def test_last
609
- authors = Author.scoped
610
- assert_equal authors(:bob), authors.last
611
- end
612
-
613
- def test_destroy_all
614
- davids = Author.where(:name => 'David')
615
-
616
- # Force load
617
- assert_equal [authors(:david)], davids.to_a
618
- assert davids.loaded?
619
-
620
- assert_difference('Author.count', -1) { davids.destroy_all }
621
-
622
- assert_equal [], davids.to_a
623
- assert davids.loaded?
624
- end
625
-
626
- def test_delete_all
627
- davids = Author.where(:name => 'David')
628
-
629
- assert_difference('Author.count', -1) { davids.delete_all }
630
- assert ! davids.loaded?
631
- end
632
-
633
- def test_delete_all_loaded
634
- davids = Author.where(:name => 'David')
635
-
636
- # Force load
637
- assert_equal [authors(:david)], davids.to_a
638
- assert davids.loaded?
639
-
640
- assert_difference('Author.count', -1) { davids.delete_all }
641
-
642
- assert_equal [], davids.to_a
643
- assert davids.loaded?
644
- end
645
-
646
- def test_select_argument_error
647
- assert_raises(ArgumentError) { Developer.select }
648
- end
649
-
650
- def test_relation_merging
651
- devs = Developer.where("salary >= 80000").merge(Developer.limit(2)).merge(Developer.order('id ASC').where("id < 3"))
652
- assert_equal [developers(:david), developers(:jamis)], devs.to_a
653
-
654
- dev_with_count = Developer.limit(1).merge(Developer.order('id DESC')).merge(Developer.select('developers.*'))
655
- assert_equal [developers(:poor_jamis)], dev_with_count.to_a
656
- end
657
-
658
- def test_relation_merging_with_eager_load
659
- relations = []
660
- relations << Post.order('comments.id DESC').merge(Post.eager_load(:last_comment)).merge(Post.scoped)
661
- relations << Post.eager_load(:last_comment).merge(Post.order('comments.id DESC')).merge(Post.scoped)
662
-
663
- relations.each do |posts|
664
- post = posts.find { |p| p.id == 1 }
665
- assert_equal Post.find(1).last_comment, post.last_comment
666
- end
667
- end
668
-
669
- def test_relation_merging_with_locks
670
- devs = Developer.lock.where("salary >= 80000").order("id DESC").merge(Developer.limit(2))
671
- assert_present devs.locked
672
- end
673
-
674
- def test_relation_merging_with_preload
675
- ActiveRecord::IdentityMap.without do
676
- [Post.scoped.merge(Post.preload(:author)), Post.preload(:author).merge(Post.scoped)].each do |posts|
677
- assert_queries(2) { assert posts.order(:id).first.author }
678
- end
679
- end
680
- end
681
-
682
- def test_relation_merging_with_joins
683
- comments = Comment.joins(:post).where(:body => 'Thank you for the welcome').merge(Post.where(:body => 'Such a lovely day'))
684
- assert_equal 1, comments.count
685
- end
686
-
687
- def test_count
688
- posts = Post.scoped
689
-
690
- assert_equal 11, posts.count
691
- assert_equal 11, posts.count(:all)
692
- assert_equal 11, posts.count(:id)
693
-
694
- assert_equal 1, posts.where('comments_count > 1').count
695
- assert_equal 9, posts.where(:comments_count => 0).count
696
- end
697
-
698
- def test_count_with_distinct
699
- posts = Post.scoped
700
-
701
- assert_equal 3, posts.count(:comments_count, :distinct => true)
702
- assert_equal 11, posts.count(:comments_count, :distinct => false)
703
-
704
- assert_equal 3, posts.select(:comments_count).count(:distinct => true)
705
- assert_equal 11, posts.select(:comments_count).count(:distinct => false)
706
- end
707
-
708
- def test_count_explicit_columns
709
- Post.update_all(:comments_count => nil)
710
- posts = Post.scoped
711
-
712
- assert_equal [0], posts.select('comments_count').where('id is not null').group('id').order('id').count.values.uniq
713
- assert_equal 0, posts.where('id is not null').select('comments_count').count
714
-
715
- assert_equal 11, posts.select('comments_count').count('id')
716
- assert_equal 0, posts.select('comments_count').count
717
- assert_equal 0, posts.count(:comments_count)
718
- assert_equal 0, posts.count('comments_count')
719
- end
720
-
721
- def test_multiple_selects
722
- post = Post.scoped.select('comments_count').select('title').order("id ASC").first
723
- assert_equal "Welcome to the weblog", post.title
724
- assert_equal 2, post.comments_count
725
- end
726
-
727
- def test_size
728
- posts = Post.scoped
729
-
730
- assert_queries(1) { assert_equal 11, posts.size }
731
- assert ! posts.loaded?
732
-
733
- best_posts = posts.where(:comments_count => 0)
734
- best_posts.to_a # force load
735
- assert_no_queries { assert_equal 9, best_posts.size }
736
- end
737
-
738
- def test_size_with_limit
739
- posts = Post.limit(10)
740
-
741
- assert_queries(1) { assert_equal 10, posts.size }
742
- assert ! posts.loaded?
743
-
744
- best_posts = posts.where(:comments_count => 0)
745
- best_posts.to_a # force load
746
- assert_no_queries { assert_equal 9, best_posts.size }
747
- end
748
-
749
- def test_size_with_zero_limit
750
- posts = Post.limit(0)
751
-
752
- assert_no_queries { assert_equal 0, posts.size }
753
- assert ! posts.loaded?
754
-
755
- posts.to_a # force load
756
- assert_no_queries { assert_equal 0, posts.size }
757
- end
758
-
759
- def test_empty_with_zero_limit
760
- posts = Post.limit(0)
761
-
762
- assert_no_queries { assert_equal true, posts.empty? }
763
- assert ! posts.loaded?
764
- end
765
-
766
- def test_count_complex_chained_relations
767
- posts = Post.select('comments_count').where('id is not null').group("author_id").where("comments_count > 0")
768
-
769
- expected = { 1 => 2 }
770
- assert_equal expected, posts.count
771
- end
772
-
773
- def test_empty
774
- posts = Post.scoped
775
-
776
- assert_queries(1) { assert_equal false, posts.empty? }
777
- assert ! posts.loaded?
778
-
779
- no_posts = posts.where(:title => "")
780
- assert_queries(1) { assert_equal true, no_posts.empty? }
781
- assert ! no_posts.loaded?
782
-
783
- best_posts = posts.where(:comments_count => 0)
784
- best_posts.to_a # force load
785
- assert_no_queries { assert_equal false, best_posts.empty? }
786
- end
787
-
788
- def test_empty_complex_chained_relations
789
- posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
790
-
791
- assert_queries(1) { assert_equal false, posts.empty? }
792
- assert ! posts.loaded?
793
-
794
- no_posts = posts.where(:title => "")
795
- assert_queries(1) { assert_equal true, no_posts.empty? }
796
- assert ! no_posts.loaded?
797
- end
798
-
799
- def test_any
800
- posts = Post.scoped
801
-
802
- # This test was failing when run on its own (as opposed to running the entire suite).
803
- # The second line in the assert_queries block was causing visit_Arel_Attributes_Attribute
804
- # in Arel::Visitors::ToSql to trigger a SHOW TABLES query. Running that line here causes
805
- # the SHOW TABLES result to be cached so we don't have to do it again in the block.
806
- #
807
- # This is obviously a rubbish fix but it's the best I can come up with for now...
808
- posts.where(:id => nil).any?
809
-
810
- assert_queries(3) do
811
- assert posts.any? # Uses COUNT()
812
- assert ! posts.where(:id => nil).any?
813
-
814
- assert posts.any? {|p| p.id > 0 }
815
- assert ! posts.any? {|p| p.id <= 0 }
816
- end
817
-
818
- assert posts.loaded?
819
- end
820
-
821
- def test_many
822
- posts = Post.scoped
823
-
824
- assert_queries(2) do
825
- assert posts.many? # Uses COUNT()
826
- assert posts.many? {|p| p.id > 0 }
827
- assert ! posts.many? {|p| p.id < 2 }
828
- end
829
-
830
- assert posts.loaded?
831
- end
832
-
833
- def test_many_with_limits
834
- posts = Post.scoped
835
-
836
- assert posts.many?
837
- assert ! posts.limit(1).many?
838
- end
839
-
840
- def test_build
841
- posts = Post.scoped
842
-
843
- post = posts.new
844
- assert_kind_of Post, post
845
- end
846
-
847
- def test_scoped_build
848
- posts = Post.where(:title => 'You told a lie')
849
-
850
- post = posts.new
851
- assert_kind_of Post, post
852
- assert_equal 'You told a lie', post.title
853
- end
854
-
855
- def test_create
856
- birds = Bird.scoped
857
-
858
- sparrow = birds.create
859
- assert_kind_of Bird, sparrow
860
- assert !sparrow.persisted?
861
-
862
- hen = birds.where(:name => 'hen').create
863
- assert hen.persisted?
864
- assert_equal 'hen', hen.name
865
- end
866
-
867
- def test_create_bang
868
- birds = Bird.scoped
869
-
870
- assert_raises(ActiveRecord::RecordInvalid) { birds.create! }
871
-
872
- hen = birds.where(:name => 'hen').create!
873
- assert_kind_of Bird, hen
874
- assert hen.persisted?
875
- assert_equal 'hen', hen.name
876
- end
877
-
878
- def test_first_or_create
879
- parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot')
880
- assert_kind_of Bird, parrot
881
- assert parrot.persisted?
882
- assert_equal 'parrot', parrot.name
883
- assert_equal 'green', parrot.color
884
-
885
- same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet')
886
- assert_kind_of Bird, same_parrot
887
- assert same_parrot.persisted?
888
- assert_equal parrot, same_parrot
889
- end
890
-
891
- def test_first_or_create_with_no_parameters
892
- parrot = Bird.where(:color => 'green').first_or_create
893
- assert_kind_of Bird, parrot
894
- assert !parrot.persisted?
895
- assert_equal 'green', parrot.color
896
- end
897
-
898
- def test_first_or_create_with_block
899
- parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parrot' }
900
- assert_kind_of Bird, parrot
901
- assert parrot.persisted?
902
- assert_equal 'green', parrot.color
903
- assert_equal 'parrot', parrot.name
904
-
905
- same_parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parakeet' }
906
- assert_equal parrot, same_parrot
907
- end
908
-
909
- def test_first_or_create_with_array
910
- several_green_birds = Bird.where(:color => 'green').first_or_create([{:name => 'parrot'}, {:name => 'parakeet'}])
911
- assert_kind_of Array, several_green_birds
912
- several_green_birds.each { |bird| assert bird.persisted? }
913
-
914
- same_parrot = Bird.where(:color => 'green').first_or_create([{:name => 'hummingbird'}, {:name => 'macaw'}])
915
- assert_kind_of Bird, same_parrot
916
- assert_equal several_green_birds.first, same_parrot
917
- end
918
-
919
- def test_first_or_create_bang_with_valid_options
920
- parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot')
921
- assert_kind_of Bird, parrot
922
- assert parrot.persisted?
923
- assert_equal 'parrot', parrot.name
924
- assert_equal 'green', parrot.color
925
-
926
- same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet')
927
- assert_kind_of Bird, same_parrot
928
- assert same_parrot.persisted?
929
- assert_equal parrot, same_parrot
930
- end
931
-
932
- def test_first_or_create_bang_with_invalid_options
933
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) }
934
- end
935
-
936
- def test_first_or_create_bang_with_no_parameters
937
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create! }
938
- end
939
-
940
- def test_first_or_create_bang_with_valid_block
941
- parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parrot' }
942
- assert_kind_of Bird, parrot
943
- assert parrot.persisted?
944
- assert_equal 'green', parrot.color
945
- assert_equal 'parrot', parrot.name
946
-
947
- same_parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parakeet' }
948
- assert_equal parrot, same_parrot
949
- end
950
-
951
- def test_first_or_create_bang_with_invalid_block
952
- assert_raise(ActiveRecord::RecordInvalid) do
953
- Bird.where(:color => 'green').first_or_create! { |bird| bird.pirate_id = 1 }
954
- end
955
- end
956
-
957
- def test_first_or_create_with_valid_array
958
- several_green_birds = Bird.where(:color => 'green').first_or_create!([{:name => 'parrot'}, {:name => 'parakeet'}])
959
- assert_kind_of Array, several_green_birds
960
- several_green_birds.each { |bird| assert bird.persisted? }
961
-
962
- same_parrot = Bird.where(:color => 'green').first_or_create!([{:name => 'hummingbird'}, {:name => 'macaw'}])
963
- assert_kind_of Bird, same_parrot
964
- assert_equal several_green_birds.first, same_parrot
965
- end
966
-
967
- def test_first_or_create_with_invalid_array
968
- assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!([ {:name => 'parrot'}, {:pirate_id => 1} ]) }
969
- end
970
-
971
- def test_first_or_initialize
972
- parrot = Bird.where(:color => 'green').first_or_initialize(:name => 'parrot')
973
- assert_kind_of Bird, parrot
974
- assert !parrot.persisted?
975
- assert parrot.valid?
976
- assert parrot.new_record?
977
- assert_equal 'parrot', parrot.name
978
- assert_equal 'green', parrot.color
979
- end
980
-
981
- def test_first_or_initialize_with_no_parameters
982
- parrot = Bird.where(:color => 'green').first_or_initialize
983
- assert_kind_of Bird, parrot
984
- assert !parrot.persisted?
985
- assert !parrot.valid?
986
- assert parrot.new_record?
987
- assert_equal 'green', parrot.color
988
- end
989
-
990
- def test_first_or_initialize_with_block
991
- parrot = Bird.where(:color => 'green').first_or_initialize { |bird| bird.name = 'parrot' }
992
- assert_kind_of Bird, parrot
993
- assert !parrot.persisted?
994
- assert parrot.valid?
995
- assert parrot.new_record?
996
- assert_equal 'green', parrot.color
997
- assert_equal 'parrot', parrot.name
998
- end
999
-
1000
- def test_explicit_create_scope
1001
- hens = Bird.where(:name => 'hen')
1002
- assert_equal 'hen', hens.new.name
1003
-
1004
- hens = hens.create_with(:name => 'cock')
1005
- assert_equal 'cock', hens.new.name
1006
- end
1007
-
1008
- def test_except
1009
- relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1010
- assert_equal [posts(:welcome)], relation.all
1011
-
1012
- author_posts = relation.except(:order, :limit)
1013
- assert_equal Post.where(:author_id => 1).all, author_posts.all
1014
-
1015
- all_posts = relation.except(:where, :order, :limit)
1016
- assert_equal Post.all, all_posts.all
1017
- end
1018
-
1019
- def test_extensions_with_except
1020
- assert_equal 2, Topic.named_extension.order(:author_name).except(:order).two
1021
- end
1022
-
1023
- def test_only
1024
- relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1025
- assert_equal [posts(:welcome)], relation.all
1026
-
1027
- author_posts = relation.only(:where)
1028
- assert_equal Post.where(:author_id => 1).all, author_posts.all
1029
-
1030
- all_posts = relation.only(:limit)
1031
- assert_equal Post.limit(1).all.first, all_posts.first
1032
- end
1033
-
1034
- def test_extensions_with_only
1035
- assert_equal 2, Topic.named_extension.order(:author_name).only(:order).two
1036
- end
1037
-
1038
- def test_anonymous_extension
1039
- relation = Post.where(:author_id => 1).order('id ASC').extending do
1040
- def author
1041
- 'lifo'
1042
- end
1043
- end
1044
-
1045
- assert_equal "lifo", relation.author
1046
- assert_equal "lifo", relation.limit(1).author
1047
- end
1048
-
1049
- def test_named_extension
1050
- relation = Post.where(:author_id => 1).order('id ASC').extending(Post::NamedExtension)
1051
- assert_equal "lifo", relation.author
1052
- assert_equal "lifo", relation.limit(1).author
1053
- end
1054
-
1055
- def test_order_by_relation_attribute
1056
- assert_equal Post.order(Post.arel_table[:title]).all, Post.order("title").all
1057
- end
1058
-
1059
- def test_order_with_find_with_order
1060
- assert_equal 'zyke', CoolCar.order('name desc').find(:first, :order => 'id').name
1061
- assert_equal 'zyke', FastCar.order('name desc').find(:first, :order => 'id').name
1062
- end
1063
-
1064
- def test_default_scope_order_with_scope_order
1065
- assert_equal 'zyke', CoolCar.order_using_new_style.limit(1).first.name
1066
- assert_equal 'zyke', CoolCar.order_using_old_style.limit(1).first.name
1067
- assert_equal 'zyke', FastCar.order_using_new_style.limit(1).first.name
1068
- assert_equal 'zyke', FastCar.order_using_old_style.limit(1).first.name
1069
- end
1070
-
1071
- def test_order_using_scoping
1072
- car1 = CoolCar.order('id DESC').scoping do
1073
- CoolCar.find(:first, :order => 'id asc')
1074
- end
1075
- assert_equal 'zyke', car1.name
1076
-
1077
- car2 = FastCar.order('id DESC').scoping do
1078
- FastCar.find(:first, :order => 'id asc')
1079
- end
1080
- assert_equal 'zyke', car2.name
1081
- end
1082
-
1083
- def test_unscoped_block_style
1084
- assert_equal 'honda', CoolCar.unscoped { CoolCar.order_using_new_style.limit(1).first.name}
1085
- assert_equal 'honda', CoolCar.unscoped { CoolCar.order_using_old_style.limit(1).first.name}
1086
-
1087
- assert_equal 'honda', FastCar.unscoped { FastCar.order_using_new_style.limit(1).first.name}
1088
- assert_equal 'honda', FastCar.unscoped { FastCar.order_using_old_style.limit(1).first.name}
1089
- end
1090
-
1091
- def test_intersection_with_array
1092
- relation = Author.where(:name => "David")
1093
- rails_author = relation.first
1094
-
1095
- assert_equal [rails_author], [rails_author] & relation
1096
- assert_equal [rails_author], relation & [rails_author]
1097
- end
1098
-
1099
- def test_removing_limit_with_options
1100
- assert_not_equal 1, Post.limit(1).all(:limit => nil).count
1101
- end
1102
-
1103
- def test_primary_key
1104
- assert_equal "id", Post.scoped.primary_key
1105
- end
1106
-
1107
- def test_eager_loading_with_conditions_on_joins
1108
- scope = Post.includes(:comments)
1109
-
1110
- # This references the comments table, and so it should cause the comments to be eager
1111
- # loaded via a JOIN, rather than by subsequent queries.
1112
- scope = scope.joins(
1113
- Post.arel_table.create_join(
1114
- Post.arel_table,
1115
- Post.arel_table.create_on(Comment.arel_table[:id].eq(3))
1116
- )
1117
- )
1118
-
1119
- assert scope.eager_loading?
1120
- end
1121
-
1122
- def test_ordering_with_extra_spaces
1123
- assert_equal authors(:david), Author.order('id DESC , name DESC').last
1124
- end
1125
-
1126
- def test_update_all_with_joins
1127
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1128
- count = comments.count
1129
-
1130
- assert_equal count, comments.update_all(:post_id => posts(:thinking).id)
1131
- assert_equal posts(:thinking), comments(:greetings).post
1132
- end
1133
-
1134
- def test_update_all_with_joins_and_limit
1135
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).limit(1)
1136
- assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
1137
- end
1138
-
1139
- def test_update_all_with_joins_and_limit_and_order
1140
- comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('comments.id').limit(1)
1141
- assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
1142
- assert_equal posts(:thinking), comments(:greetings).post
1143
- assert_equal posts(:welcome), comments(:more_greetings).post
1144
- end
1145
-
1146
- unless current_adapter?(:IBM_DBAdapter)
1147
- #IBM_DB does not support offset on subselect of the update statement
1148
- def test_update_all_with_joins_and_offset
1149
- all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1150
- count = all_comments.count
1151
- comments = all_comments.offset(1)
1152
-
1153
- assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1154
- end
1155
-
1156
- def test_update_all_with_joins_and_offset_and_order
1157
- all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('posts.id', 'comments.id')
1158
- count = all_comments.count
1159
- comments = all_comments.offset(1)
1160
-
1161
- assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1162
- assert_equal posts(:thinking), comments(:more_greetings).post
1163
- assert_equal posts(:welcome), comments(:greetings).post
1164
- end
1165
- end
1166
-
1167
- def test_uniq
1168
- tag1 = Tag.create(:name => 'Foo')
1169
- tag2 = Tag.create(:name => 'Foo')
1170
-
1171
- query = Tag.select(:name).where(:id => [tag1.id, tag2.id])
1172
-
1173
- assert_equal ['Foo', 'Foo'], query.map(&:name)
1174
- assert_sql(/DISTINCT/) do
1175
- assert_equal ['Foo'], query.uniq.map(&:name)
1176
- end
1177
- assert_sql(/DISTINCT/) do
1178
- assert_equal ['Foo'], query.uniq(true).map(&:name)
1179
- end
1180
- assert_equal ['Foo', 'Foo'], query.uniq(true).uniq(false).map(&:name)
1181
- end
1182
- end
1
+ require "cases/helper"
2
+ require 'models/tag'
3
+ require 'models/tagging'
4
+ require 'models/post'
5
+ require 'models/topic'
6
+ require 'models/comment'
7
+ require 'models/reply'
8
+ require 'models/author'
9
+ require 'models/comment'
10
+ require 'models/entrant'
11
+ require 'models/developer'
12
+ require 'models/company'
13
+ require 'models/bird'
14
+ require 'models/car'
15
+ require 'models/engine'
16
+ require 'models/tyre'
17
+ require 'models/minivan'
18
+
19
+
20
+ class RelationTest < ActiveRecord::TestCase
21
+ fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
22
+ :tags, :taggings, :cars, :minivans
23
+
24
+ def test_do_not_double_quote_string_id
25
+ van = Minivan.last
26
+ assert van
27
+ assert_equal van.id, Minivan.where(:minivan_id => van).to_a.first.minivan_id
28
+ end
29
+
30
+ def test_do_not_double_quote_string_id_with_array
31
+ van = Minivan.last
32
+ assert van
33
+ assert_equal van, Minivan.where(:minivan_id => [van]).to_a.first
34
+ end
35
+
36
+ def test_bind_values
37
+ relation = Post.scoped
38
+ assert_equal [], relation.bind_values
39
+
40
+ relation2 = relation.bind 'foo'
41
+ assert_equal %w{ foo }, relation2.bind_values
42
+ assert_equal [], relation.bind_values
43
+ end
44
+
45
+ def test_two_scopes_with_includes_should_not_drop_any_include
46
+ car = Car.incl_engines.incl_tyres.first
47
+ assert_no_queries { car.tyres.length }
48
+ assert_no_queries { car.engines.length }
49
+ end
50
+
51
+ def test_dynamic_finder
52
+ x = Post.where('author_id = ?', 1)
53
+ assert x.klass.respond_to?(:find_by_id), '@klass should handle dynamic finders'
54
+ end
55
+
56
+ def test_multivalue_where
57
+ posts = Post.where('author_id = ? AND id = ?', 1, 1)
58
+ assert_equal 1, posts.to_a.size
59
+ end
60
+
61
+ def test_scoped
62
+ topics = Topic.scoped
63
+ assert_kind_of ActiveRecord::Relation, topics
64
+ assert_equal 4, topics.size
65
+ end
66
+
67
+ def test_to_json
68
+ assert_nothing_raised { Bird.scoped.to_json }
69
+ assert_nothing_raised { Bird.scoped.all.to_json }
70
+ end
71
+
72
+ def test_to_yaml
73
+ assert_nothing_raised { Bird.scoped.to_yaml }
74
+ assert_nothing_raised { Bird.scoped.all.to_yaml }
75
+ end
76
+
77
+ def test_to_xml
78
+ assert_nothing_raised { Bird.scoped.to_xml }
79
+ assert_nothing_raised { Bird.scoped.all.to_xml }
80
+ end
81
+
82
+ def test_scoped_all
83
+ topics = Topic.scoped.all
84
+ assert_kind_of Array, topics
85
+ assert_no_queries { assert_equal 4, topics.size }
86
+ end
87
+
88
+ def test_loaded_all
89
+ topics = Topic.scoped
90
+
91
+ assert_queries(1) do
92
+ 2.times { assert_equal 4, topics.all.size }
93
+ end
94
+
95
+ assert topics.loaded?
96
+ end
97
+
98
+ def test_scoped_first
99
+ topics = Topic.scoped.order('id ASC')
100
+
101
+ assert_queries(1) do
102
+ 2.times { assert_equal "The First Topic", topics.first.title }
103
+ end
104
+
105
+ assert ! topics.loaded?
106
+ end
107
+
108
+ def test_loaded_first
109
+ topics = Topic.scoped.order('id ASC')
110
+
111
+ assert_queries(1) do
112
+ topics.all # force load
113
+ 2.times { assert_equal "The First Topic", topics.first.title }
114
+ end
115
+
116
+ assert topics.loaded?
117
+ end
118
+
119
+ def test_reload
120
+ topics = Topic.scoped
121
+
122
+ assert_queries(1) do
123
+ 2.times { topics.to_a }
124
+ end
125
+
126
+ assert topics.loaded?
127
+
128
+ original_size = topics.to_a.size
129
+ Topic.create! :title => 'fake'
130
+
131
+ assert_queries(1) { topics.reload }
132
+ assert_equal original_size + 1, topics.size
133
+ assert topics.loaded?
134
+ end
135
+
136
+ def test_finding_with_conditions
137
+ assert_equal ["David"], Author.where(:name => 'David').map(&:name)
138
+ assert_equal ['Mary'], Author.where(["name = ?", 'Mary']).map(&:name)
139
+ assert_equal ['Mary'], Author.where("name = ?", 'Mary').map(&:name)
140
+ end
141
+
142
+ def test_finding_with_order
143
+ topics = Topic.order('id')
144
+ assert_equal 4, topics.to_a.size
145
+ assert_equal topics(:first).title, topics.first.title
146
+ end
147
+
148
+
149
+ def test_finding_with_arel_order
150
+ topics = Topic.order(Topic.arel_table[:id].asc)
151
+ assert_equal 4, topics.to_a.size
152
+ assert_equal topics(:first).title, topics.first.title
153
+ end
154
+
155
+ def test_finding_last_with_arel_order
156
+ topics = Topic.order(Topic.arel_table[:id].asc)
157
+ assert_equal topics(:fourth).title, topics.last.title
158
+ end
159
+
160
+ def test_finding_with_order_concatenated
161
+ topics = Topic.order('author_name').order('title')
162
+ assert_equal 4, topics.to_a.size
163
+ assert_equal topics(:fourth).title, topics.first.title
164
+ end
165
+
166
+ def test_finding_with_reorder
167
+ topics = Topic.order('author_name').order('title').reorder('id').all
168
+ topics_titles = topics.map{ |t| t.title }
169
+ assert_equal ['The First Topic', 'The Second Topic of the day', 'The Third Topic of the day', 'The Fourth Topic of the day'], topics_titles
170
+ end
171
+
172
+ def test_finding_with_order_and_take
173
+ entrants = Entrant.order("id ASC").limit(2).to_a
174
+
175
+ assert_equal 2, entrants.size
176
+ assert_equal entrants(:first).name, entrants.first.name
177
+ end
178
+
179
+ def test_finding_with_cross_table_order_and_limit
180
+ tags = Tag.includes(:taggings).
181
+ order("tags.name asc", "taggings.taggable_id asc", "REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").
182
+ limit(1).to_a
183
+ assert_equal 1, tags.length
184
+ end
185
+
186
+ def test_finding_with_complex_order_and_limit
187
+ tags = Tag.includes(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").limit(1).to_a
188
+ assert_equal 1, tags.length
189
+ end
190
+
191
+ def test_finding_with_complex_order
192
+ tags = Tag.includes(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a
193
+ assert_equal 3, tags.length
194
+ end
195
+
196
+ def test_finding_with_order_limit_and_offset
197
+ entrants = Entrant.order("id ASC").limit(2).offset(1)
198
+
199
+ assert_equal 2, entrants.to_a.size
200
+ assert_equal entrants(:second).name, entrants.first.name
201
+
202
+ entrants = Entrant.order("id ASC").limit(2).offset(2)
203
+ assert_equal 1, entrants.to_a.size
204
+ assert_equal entrants(:third).name, entrants.first.name
205
+ end
206
+
207
+ def test_finding_with_group
208
+ developers = Developer.group("salary").select("salary").to_a
209
+ assert_equal 4, developers.size
210
+ assert_equal 4, developers.map(&:salary).uniq.size
211
+ end
212
+
213
+ def test_select_with_block
214
+ even_ids = Developer.scoped.select {|d| d.id % 2 == 0 }.map(&:id)
215
+ assert_equal [2, 4, 6, 8, 10], even_ids.sort
216
+ end
217
+
218
+ def test_joins_with_nil_argument
219
+ assert_nothing_raised { DependentFirm.joins(nil).first }
220
+ end
221
+
222
+ def test_finding_with_hash_conditions_on_joined_table
223
+ firms = DependentFirm.joins(:account).where({:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}).to_a
224
+ assert_equal 1, firms.size
225
+ assert_equal companies(:rails_core), firms.first
226
+ end
227
+
228
+ def test_find_all_with_join
229
+ developers_on_project_one = Developer.joins('LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id').
230
+ where('project_id=1').to_a
231
+
232
+ assert_equal 3, developers_on_project_one.length
233
+ developer_names = developers_on_project_one.map { |d| d.name }
234
+ assert developer_names.include?('David')
235
+ assert developer_names.include?('Jamis')
236
+ end
237
+
238
+ def test_find_on_hash_conditions
239
+ assert_equal Topic.find(:all, :conditions => {:approved => false}), Topic.where({ :approved => false }).to_a
240
+ end
241
+
242
+ def test_joins_with_string_array
243
+ person_with_reader_and_post = Post.joins([
244
+ "INNER JOIN categorizations ON categorizations.post_id = posts.id",
245
+ "INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
246
+ ]
247
+ ).to_a
248
+ assert_equal 1, person_with_reader_and_post.size
249
+ end
250
+
251
+ def test_scoped_responds_to_delegated_methods
252
+ relation = Topic.scoped
253
+
254
+ ["map", "uniq", "sort", "insert", "delete", "update"].each do |method|
255
+ assert_respond_to relation, method, "Topic.scoped should respond to #{method.inspect}"
256
+ end
257
+ end
258
+
259
+ def test_respond_to_delegates_to_relation
260
+ relation = Topic.scoped
261
+ fake_arel = Struct.new(:responds) {
262
+ def respond_to? method, access = false
263
+ responds << [method, access]
264
+ end
265
+ }.new []
266
+
267
+ relation.extend(Module.new { attr_accessor :arel })
268
+ relation.arel = fake_arel
269
+
270
+ relation.respond_to?(:matching_attributes)
271
+ assert_equal [:matching_attributes, false], fake_arel.responds.first
272
+
273
+ fake_arel.responds = []
274
+ relation.respond_to?(:matching_attributes, true)
275
+ assert_equal [:matching_attributes, true], fake_arel.responds.first
276
+ end
277
+
278
+ def test_respond_to_dynamic_finders
279
+ relation = Topic.scoped
280
+
281
+ ["find_by_title", "find_by_title_and_author_name", "find_or_create_by_title", "find_or_initialize_by_title_and_author_name"].each do |method|
282
+ assert_respond_to relation, method, "Topic.scoped should respond to #{method.inspect}"
283
+ end
284
+ end
285
+
286
+ def test_respond_to_class_methods_and_scopes
287
+ assert DeveloperOrderedBySalary.scoped.respond_to?(:all_ordered_by_name)
288
+ assert Topic.scoped.respond_to?(:by_lifo)
289
+ end
290
+
291
+ def test_find_with_readonly_option
292
+ Developer.scoped.each { |d| assert !d.readonly? }
293
+ Developer.scoped.readonly.each { |d| assert d.readonly? }
294
+ end
295
+
296
+ def test_eager_association_loading_of_stis_with_multiple_references
297
+ authors = Author.eager_load(:posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } }).
298
+ order('comments.body, very_special_comments_posts.body').where('posts.id = 4').to_a
299
+
300
+ assert_equal [authors(:david)], authors
301
+ assert_no_queries do
302
+ authors.first.posts.first.special_comments.first.post.special_comments
303
+ authors.first.posts.first.special_comments.first.post.very_special_comment
304
+ end
305
+ end
306
+
307
+ def test_find_with_preloaded_associations
308
+ assert_queries(2) do
309
+ posts = Post.preload(:comments).order('posts.id')
310
+ assert posts.first.comments.first
311
+ end
312
+
313
+ assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
314
+ posts = Post.preload(:comments).order('posts.id')
315
+ assert posts.first.comments.first
316
+ end
317
+
318
+ assert_queries(2) do
319
+ posts = Post.preload(:author).order('posts.id')
320
+ assert posts.first.author
321
+ end
322
+
323
+ assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
324
+ posts = Post.preload(:author).order('posts.id')
325
+ assert posts.first.author
326
+ end
327
+
328
+ assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 3) do
329
+ posts = Post.preload(:author, :comments).order('posts.id')
330
+ assert posts.first.author
331
+ assert posts.first.comments.first
332
+ end
333
+ end
334
+
335
+ def test_find_with_included_associations
336
+ assert_queries(2) do
337
+ posts = Post.includes(:comments).order('posts.id')
338
+ assert posts.first.comments.first
339
+ end
340
+
341
+ assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) do
342
+ posts = Post.scoped.includes(:comments).order('posts.id')
343
+ assert posts.first.comments.first
344
+ end
345
+
346
+ assert_queries(2) do
347
+ posts = Post.includes(:author).order('posts.id')
348
+ assert posts.first.author
349
+ end
350
+
351
+ assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 3) do
352
+ posts = Post.includes(:author, :comments).order('posts.id')
353
+ assert posts.first.author
354
+ assert posts.first.comments.first
355
+ end
356
+ end
357
+
358
+ def test_default_scope_with_conditions_string
359
+ assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeveloperCalledDavid.scoped.map(&:id).sort
360
+ assert_nil DeveloperCalledDavid.create!.name
361
+ end
362
+
363
+ def test_default_scope_with_conditions_hash
364
+ assert_equal Developer.find_all_by_name('Jamis').map(&:id).sort, DeveloperCalledJamis.scoped.map(&:id).sort
365
+ assert_equal 'Jamis', DeveloperCalledJamis.create!.name
366
+ end
367
+
368
+ def test_default_scoping_finder_methods
369
+ developers = DeveloperCalledDavid.order('id').map(&:id).sort
370
+ assert_equal Developer.find_all_by_name('David').map(&:id).sort, developers
371
+ end
372
+
373
+ def test_loading_with_one_association
374
+ posts = Post.preload(:comments)
375
+ post = posts.find { |p| p.id == 1 }
376
+ assert_equal 2, post.comments.size
377
+ assert post.comments.include?(comments(:greetings))
378
+
379
+ post = Post.where("posts.title = 'Welcome to the weblog'").preload(:comments).first
380
+ assert_equal 2, post.comments.size
381
+ assert post.comments.include?(comments(:greetings))
382
+
383
+ posts = Post.preload(:last_comment)
384
+ post = posts.find { |p| p.id == 1 }
385
+ assert_equal Post.find(1).last_comment, post.last_comment
386
+ end
387
+
388
+ def test_loading_with_one_association_with_non_preload
389
+ posts = Post.eager_load(:last_comment).order('comments.id DESC')
390
+ post = posts.find { |p| p.id == 1 }
391
+ assert_equal Post.find(1).last_comment, post.last_comment
392
+ end
393
+
394
+ def test_dynamic_find_by_attributes_should_yield_found_object
395
+ david = authors(:david)
396
+ yielded_value = nil
397
+ Author.find_by_name(david.name) do |author|
398
+ yielded_value = author
399
+ end
400
+ assert_equal david, yielded_value
401
+ end
402
+
403
+ def test_dynamic_find_by_attributes
404
+ david = authors(:david)
405
+ author = Author.preload(:taggings).find_by_id(david.id)
406
+ expected_taggings = taggings(:welcome_general, :thinking_general)
407
+
408
+ assert_no_queries do
409
+ assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
410
+ end
411
+
412
+ authors = Author.scoped
413
+ assert_equal david, authors.find_by_id_and_name(david.id, david.name)
414
+ assert_equal david, authors.find_by_id_and_name!(david.id, david.name)
415
+ end
416
+
417
+ def test_dynamic_find_by_attributes_bang
418
+ author = Author.scoped.find_by_id!(authors(:david).id)
419
+ assert_equal "David", author.name
420
+
421
+ assert_raises(ActiveRecord::RecordNotFound) { Author.scoped.find_by_id_and_name!(20, 'invalid') }
422
+ end
423
+
424
+ def test_dynamic_find_all_by_attributes
425
+ authors = Author.scoped
426
+
427
+ davids = authors.find_all_by_name('David')
428
+ assert_kind_of Array, davids
429
+ assert_equal [authors(:david)], davids
430
+ end
431
+
432
+ def test_dynamic_find_or_initialize_by_attributes
433
+ authors = Author.scoped
434
+
435
+ lifo = authors.find_or_initialize_by_name('Lifo')
436
+ assert_equal "Lifo", lifo.name
437
+ assert !lifo.persisted?
438
+
439
+ assert_equal authors(:david), authors.find_or_initialize_by_name(:name => 'David')
440
+ end
441
+
442
+ def test_dynamic_find_or_create_by_attributes
443
+ authors = Author.scoped
444
+
445
+ lifo = authors.find_or_create_by_name('Lifo')
446
+ assert_equal "Lifo", lifo.name
447
+ assert lifo.persisted?
448
+
449
+ assert_equal authors(:david), authors.find_or_create_by_name(:name => 'David')
450
+ end
451
+
452
+ def test_dynamic_find_or_create_by_attributes_bang
453
+ authors = Author.scoped
454
+
455
+ assert_raises(ActiveRecord::RecordInvalid) { authors.find_or_create_by_name!('') }
456
+
457
+ lifo = authors.find_or_create_by_name!('Lifo')
458
+ assert_equal "Lifo", lifo.name
459
+ assert lifo.persisted?
460
+
461
+ assert_equal authors(:david), authors.find_or_create_by_name!(:name => 'David')
462
+ end
463
+
464
+ def test_find_id
465
+ authors = Author.scoped
466
+
467
+ david = authors.find(authors(:david).id)
468
+ assert_equal 'David', david.name
469
+
470
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') }
471
+ end
472
+
473
+ def test_find_ids
474
+ authors = Author.order('id ASC')
475
+
476
+ results = authors.find(authors(:david).id, authors(:mary).id)
477
+ assert_kind_of Array, results
478
+ assert_equal 2, results.size
479
+ assert_equal 'David', results[0].name
480
+ assert_equal 'Mary', results[1].name
481
+ assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
482
+
483
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') }
484
+ assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) }
485
+ end
486
+
487
+ def test_find_in_empty_array
488
+ authors = Author.scoped.where(:id => [])
489
+ assert_blank authors.all
490
+ end
491
+
492
+ def test_where_with_ar_object
493
+ author = Author.first
494
+ authors = Author.scoped.where(:id => author)
495
+ assert_equal 1, authors.all.length
496
+ end
497
+
498
+ def test_find_with_list_of_ar
499
+ author = Author.first
500
+ authors = Author.find([author])
501
+ assert_equal author, authors.first
502
+ end
503
+
504
+ class Mary < Author; end
505
+
506
+ def test_find_by_classname
507
+ Author.create!(:name => Mary.name)
508
+ assert_equal 1, Author.where(:name => Mary).size
509
+ end
510
+
511
+ def test_find_by_id_with_list_of_ar
512
+ author = Author.first
513
+ authors = Author.find_by_id([author])
514
+ assert_equal author, authors
515
+ end
516
+
517
+ def test_find_all_using_where_twice_should_or_the_relation
518
+ david = authors(:david)
519
+ relation = Author.unscoped
520
+ relation = relation.where(:name => david.name)
521
+ relation = relation.where(:name => 'Santiago')
522
+ relation = relation.where(:id => david.id)
523
+ assert_equal [], relation.all
524
+ end
525
+
526
+ def test_multi_where_ands_queries
527
+ relation = Author.unscoped
528
+ david = authors(:david)
529
+ sql = relation.where(:name => david.name).where(:name => 'Santiago').to_sql
530
+ assert_match('AND', sql)
531
+ end
532
+
533
+ def test_find_all_with_multiple_should_use_and
534
+ david = authors(:david)
535
+ relation = [
536
+ { :name => david.name },
537
+ { :name => 'Santiago' },
538
+ { :name => 'tenderlove' },
539
+ ].inject(Author.unscoped) do |memo, param|
540
+ memo.where(param)
541
+ end
542
+ assert_equal [], relation.all
543
+ end
544
+
545
+ def test_find_all_using_where_with_relation
546
+ david = authors(:david)
547
+ # switching the lines below would succeed in current rails
548
+ # assert_queries(2) {
549
+ assert_queries(1) {
550
+ relation = Author.where(:id => Author.where(:id => david.id))
551
+ assert_equal [david], relation.all
552
+ }
553
+ end
554
+
555
+ def test_find_all_using_where_with_relation_and_alternate_primary_key
556
+ cool_first = minivans(:cool_first)
557
+ # switching the lines below would succeed in current rails
558
+ # assert_queries(2) {
559
+ assert_queries(1) {
560
+ relation = Minivan.where(:minivan_id => Minivan.where(:name => cool_first.name))
561
+ assert_equal [cool_first], relation.all
562
+ }
563
+ end
564
+
565
+ def test_find_all_using_where_with_relation_does_not_alter_select_values
566
+ david = authors(:david)
567
+
568
+ subquery = Author.where(:id => david.id)
569
+
570
+ assert_queries(1) {
571
+ relation = Author.where(:id => subquery)
572
+ assert_equal [david], relation.all
573
+ }
574
+
575
+ assert_equal 0, subquery.select_values.size
576
+ end
577
+
578
+ def test_find_all_using_where_with_relation_with_joins
579
+ david = authors(:david)
580
+ assert_queries(1) {
581
+ relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
582
+ assert_equal [david], relation.all
583
+ }
584
+ end
585
+
586
+
587
+ def test_find_all_using_where_with_relation_with_select_to_build_subquery
588
+ david = authors(:david)
589
+ assert_queries(1) {
590
+ relation = Author.where(:name => Author.where(:id => david.id).select(:name))
591
+ assert_equal [david], relation.all
592
+ }
593
+ end
594
+
595
+ def test_exists
596
+ davids = Author.where(:name => 'David')
597
+ assert davids.exists?
598
+ assert davids.exists?(authors(:david).id)
599
+ assert ! davids.exists?(authors(:mary).id)
600
+ assert ! davids.exists?("42")
601
+ assert ! davids.exists?(42)
602
+
603
+ fake = Author.where(:name => 'fake author')
604
+ assert ! fake.exists?
605
+ assert ! fake.exists?(authors(:david).id)
606
+ end
607
+
608
+ def test_last
609
+ authors = Author.scoped
610
+ assert_equal authors(:bob), authors.last
611
+ end
612
+
613
+ def test_destroy_all
614
+ davids = Author.where(:name => 'David')
615
+
616
+ # Force load
617
+ assert_equal [authors(:david)], davids.to_a
618
+ assert davids.loaded?
619
+
620
+ assert_difference('Author.count', -1) { davids.destroy_all }
621
+
622
+ assert_equal [], davids.to_a
623
+ assert davids.loaded?
624
+ end
625
+
626
+ def test_delete_all
627
+ davids = Author.where(:name => 'David')
628
+
629
+ assert_difference('Author.count', -1) { davids.delete_all }
630
+ assert ! davids.loaded?
631
+ end
632
+
633
+ def test_delete_all_loaded
634
+ davids = Author.where(:name => 'David')
635
+
636
+ # Force load
637
+ assert_equal [authors(:david)], davids.to_a
638
+ assert davids.loaded?
639
+
640
+ assert_difference('Author.count', -1) { davids.delete_all }
641
+
642
+ assert_equal [], davids.to_a
643
+ assert davids.loaded?
644
+ end
645
+
646
+ def test_select_argument_error
647
+ assert_raises(ArgumentError) { Developer.select }
648
+ end
649
+
650
+ def test_relation_merging
651
+ devs = Developer.where("salary >= 80000").merge(Developer.limit(2)).merge(Developer.order('id ASC').where("id < 3"))
652
+ assert_equal [developers(:david), developers(:jamis)], devs.to_a
653
+
654
+ dev_with_count = Developer.limit(1).merge(Developer.order('id DESC')).merge(Developer.select('developers.*'))
655
+ assert_equal [developers(:poor_jamis)], dev_with_count.to_a
656
+ end
657
+
658
+ def test_relation_merging_with_eager_load
659
+ relations = []
660
+ relations << Post.order('comments.id DESC').merge(Post.eager_load(:last_comment)).merge(Post.scoped)
661
+ relations << Post.eager_load(:last_comment).merge(Post.order('comments.id DESC')).merge(Post.scoped)
662
+
663
+ relations.each do |posts|
664
+ post = posts.find { |p| p.id == 1 }
665
+ assert_equal Post.find(1).last_comment, post.last_comment
666
+ end
667
+ end
668
+
669
+ def test_relation_merging_with_locks
670
+ devs = Developer.lock.where("salary >= 80000").order("id DESC").merge(Developer.limit(2))
671
+ assert_present devs.locked
672
+ end
673
+
674
+ def test_relation_merging_with_preload
675
+ ActiveRecord::IdentityMap.without do
676
+ [Post.scoped.merge(Post.preload(:author)), Post.preload(:author).merge(Post.scoped)].each do |posts|
677
+ assert_queries(2) { assert posts.order(:id).first.author }
678
+ end
679
+ end
680
+ end
681
+
682
+ def test_relation_merging_with_joins
683
+ comments = Comment.joins(:post).where(:body => 'Thank you for the welcome').merge(Post.where(:body => 'Such a lovely day'))
684
+ assert_equal 1, comments.count
685
+ end
686
+
687
+ def test_count
688
+ posts = Post.scoped
689
+
690
+ assert_equal 11, posts.count
691
+ assert_equal 11, posts.count(:all)
692
+ assert_equal 11, posts.count(:id)
693
+
694
+ assert_equal 1, posts.where('comments_count > 1').count
695
+ assert_equal 9, posts.where(:comments_count => 0).count
696
+ end
697
+
698
+ def test_count_with_distinct
699
+ posts = Post.scoped
700
+
701
+ assert_equal 3, posts.count(:comments_count, :distinct => true)
702
+ assert_equal 11, posts.count(:comments_count, :distinct => false)
703
+
704
+ assert_equal 3, posts.select(:comments_count).count(:distinct => true)
705
+ assert_equal 11, posts.select(:comments_count).count(:distinct => false)
706
+ end
707
+
708
+ def test_count_explicit_columns
709
+ Post.update_all(:comments_count => nil)
710
+ posts = Post.scoped
711
+
712
+ assert_equal [0], posts.select('comments_count').where('id is not null').group('id').order('id').count.values.uniq
713
+ assert_equal 0, posts.where('id is not null').select('comments_count').count
714
+
715
+ assert_equal 11, posts.select('comments_count').count('id')
716
+ assert_equal 0, posts.select('comments_count').count
717
+ assert_equal 0, posts.count(:comments_count)
718
+ assert_equal 0, posts.count('comments_count')
719
+ end
720
+
721
+ def test_multiple_selects
722
+ post = Post.scoped.select('comments_count').select('title').order("id ASC").first
723
+ assert_equal "Welcome to the weblog", post.title
724
+ assert_equal 2, post.comments_count
725
+ end
726
+
727
+ def test_size
728
+ posts = Post.scoped
729
+
730
+ assert_queries(1) { assert_equal 11, posts.size }
731
+ assert ! posts.loaded?
732
+
733
+ best_posts = posts.where(:comments_count => 0)
734
+ best_posts.to_a # force load
735
+ assert_no_queries { assert_equal 9, best_posts.size }
736
+ end
737
+
738
+ def test_size_with_limit
739
+ posts = Post.limit(10)
740
+
741
+ assert_queries(1) { assert_equal 10, posts.size }
742
+ assert ! posts.loaded?
743
+
744
+ best_posts = posts.where(:comments_count => 0)
745
+ best_posts.to_a # force load
746
+ assert_no_queries { assert_equal 9, best_posts.size }
747
+ end
748
+
749
+ def test_size_with_zero_limit
750
+ posts = Post.limit(0)
751
+
752
+ assert_no_queries { assert_equal 0, posts.size }
753
+ assert ! posts.loaded?
754
+
755
+ posts.to_a # force load
756
+ assert_no_queries { assert_equal 0, posts.size }
757
+ end
758
+
759
+ def test_empty_with_zero_limit
760
+ posts = Post.limit(0)
761
+
762
+ assert_no_queries { assert_equal true, posts.empty? }
763
+ assert ! posts.loaded?
764
+ end
765
+
766
+ def test_count_complex_chained_relations
767
+ posts = Post.select('comments_count').where('id is not null').group("author_id").where("comments_count > 0")
768
+
769
+ expected = { 1 => 2 }
770
+ assert_equal expected, posts.count
771
+ end
772
+
773
+ def test_empty
774
+ posts = Post.scoped
775
+
776
+ assert_queries(1) { assert_equal false, posts.empty? }
777
+ assert ! posts.loaded?
778
+
779
+ no_posts = posts.where(:title => "")
780
+ assert_queries(1) { assert_equal true, no_posts.empty? }
781
+ assert ! no_posts.loaded?
782
+
783
+ best_posts = posts.where(:comments_count => 0)
784
+ best_posts.to_a # force load
785
+ assert_no_queries { assert_equal false, best_posts.empty? }
786
+ end
787
+
788
+ def test_empty_complex_chained_relations
789
+ posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
790
+
791
+ assert_queries(1) { assert_equal false, posts.empty? }
792
+ assert ! posts.loaded?
793
+
794
+ no_posts = posts.where(:title => "")
795
+ assert_queries(1) { assert_equal true, no_posts.empty? }
796
+ assert ! no_posts.loaded?
797
+ end
798
+
799
+ def test_any
800
+ posts = Post.scoped
801
+
802
+ # This test was failing when run on its own (as opposed to running the entire suite).
803
+ # The second line in the assert_queries block was causing visit_Arel_Attributes_Attribute
804
+ # in Arel::Visitors::ToSql to trigger a SHOW TABLES query. Running that line here causes
805
+ # the SHOW TABLES result to be cached so we don't have to do it again in the block.
806
+ #
807
+ # This is obviously a rubbish fix but it's the best I can come up with for now...
808
+ posts.where(:id => nil).any?
809
+
810
+ assert_queries(3) do
811
+ assert posts.any? # Uses COUNT()
812
+ assert ! posts.where(:id => nil).any?
813
+
814
+ assert posts.any? {|p| p.id > 0 }
815
+ assert ! posts.any? {|p| p.id <= 0 }
816
+ end
817
+
818
+ assert posts.loaded?
819
+ end
820
+
821
+ def test_many
822
+ posts = Post.scoped
823
+
824
+ assert_queries(2) do
825
+ assert posts.many? # Uses COUNT()
826
+ assert posts.many? {|p| p.id > 0 }
827
+ assert ! posts.many? {|p| p.id < 2 }
828
+ end
829
+
830
+ assert posts.loaded?
831
+ end
832
+
833
+ def test_many_with_limits
834
+ posts = Post.scoped
835
+
836
+ assert posts.many?
837
+ assert ! posts.limit(1).many?
838
+ end
839
+
840
+ def test_build
841
+ posts = Post.scoped
842
+
843
+ post = posts.new
844
+ assert_kind_of Post, post
845
+ end
846
+
847
+ def test_scoped_build
848
+ posts = Post.where(:title => 'You told a lie')
849
+
850
+ post = posts.new
851
+ assert_kind_of Post, post
852
+ assert_equal 'You told a lie', post.title
853
+ end
854
+
855
+ def test_create
856
+ birds = Bird.scoped
857
+
858
+ sparrow = birds.create
859
+ assert_kind_of Bird, sparrow
860
+ assert !sparrow.persisted?
861
+
862
+ hen = birds.where(:name => 'hen').create
863
+ assert hen.persisted?
864
+ assert_equal 'hen', hen.name
865
+ end
866
+
867
+ def test_create_bang
868
+ birds = Bird.scoped
869
+
870
+ assert_raises(ActiveRecord::RecordInvalid) { birds.create! }
871
+
872
+ hen = birds.where(:name => 'hen').create!
873
+ assert_kind_of Bird, hen
874
+ assert hen.persisted?
875
+ assert_equal 'hen', hen.name
876
+ end
877
+
878
+ def test_first_or_create
879
+ parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot')
880
+ assert_kind_of Bird, parrot
881
+ assert parrot.persisted?
882
+ assert_equal 'parrot', parrot.name
883
+ assert_equal 'green', parrot.color
884
+
885
+ same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet')
886
+ assert_kind_of Bird, same_parrot
887
+ assert same_parrot.persisted?
888
+ assert_equal parrot, same_parrot
889
+ end
890
+
891
+ def test_first_or_create_with_no_parameters
892
+ parrot = Bird.where(:color => 'green').first_or_create
893
+ assert_kind_of Bird, parrot
894
+ assert !parrot.persisted?
895
+ assert_equal 'green', parrot.color
896
+ end
897
+
898
+ def test_first_or_create_with_block
899
+ parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parrot' }
900
+ assert_kind_of Bird, parrot
901
+ assert parrot.persisted?
902
+ assert_equal 'green', parrot.color
903
+ assert_equal 'parrot', parrot.name
904
+
905
+ same_parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parakeet' }
906
+ assert_equal parrot, same_parrot
907
+ end
908
+
909
+ def test_first_or_create_with_array
910
+ several_green_birds = Bird.where(:color => 'green').first_or_create([{:name => 'parrot'}, {:name => 'parakeet'}])
911
+ assert_kind_of Array, several_green_birds
912
+ several_green_birds.each { |bird| assert bird.persisted? }
913
+
914
+ same_parrot = Bird.where(:color => 'green').first_or_create([{:name => 'hummingbird'}, {:name => 'macaw'}])
915
+ assert_kind_of Bird, same_parrot
916
+ assert_equal several_green_birds.first, same_parrot
917
+ end
918
+
919
+ def test_first_or_create_bang_with_valid_options
920
+ parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot')
921
+ assert_kind_of Bird, parrot
922
+ assert parrot.persisted?
923
+ assert_equal 'parrot', parrot.name
924
+ assert_equal 'green', parrot.color
925
+
926
+ same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet')
927
+ assert_kind_of Bird, same_parrot
928
+ assert same_parrot.persisted?
929
+ assert_equal parrot, same_parrot
930
+ end
931
+
932
+ def test_first_or_create_bang_with_invalid_options
933
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) }
934
+ end
935
+
936
+ def test_first_or_create_bang_with_no_parameters
937
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create! }
938
+ end
939
+
940
+ def test_first_or_create_bang_with_valid_block
941
+ parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parrot' }
942
+ assert_kind_of Bird, parrot
943
+ assert parrot.persisted?
944
+ assert_equal 'green', parrot.color
945
+ assert_equal 'parrot', parrot.name
946
+
947
+ same_parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parakeet' }
948
+ assert_equal parrot, same_parrot
949
+ end
950
+
951
+ def test_first_or_create_bang_with_invalid_block
952
+ assert_raise(ActiveRecord::RecordInvalid) do
953
+ Bird.where(:color => 'green').first_or_create! { |bird| bird.pirate_id = 1 }
954
+ end
955
+ end
956
+
957
+ def test_first_or_create_with_valid_array
958
+ several_green_birds = Bird.where(:color => 'green').first_or_create!([{:name => 'parrot'}, {:name => 'parakeet'}])
959
+ assert_kind_of Array, several_green_birds
960
+ several_green_birds.each { |bird| assert bird.persisted? }
961
+
962
+ same_parrot = Bird.where(:color => 'green').first_or_create!([{:name => 'hummingbird'}, {:name => 'macaw'}])
963
+ assert_kind_of Bird, same_parrot
964
+ assert_equal several_green_birds.first, same_parrot
965
+ end
966
+
967
+ def test_first_or_create_with_invalid_array
968
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!([ {:name => 'parrot'}, {:pirate_id => 1} ]) }
969
+ end
970
+
971
+ def test_first_or_initialize
972
+ parrot = Bird.where(:color => 'green').first_or_initialize(:name => 'parrot')
973
+ assert_kind_of Bird, parrot
974
+ assert !parrot.persisted?
975
+ assert parrot.valid?
976
+ assert parrot.new_record?
977
+ assert_equal 'parrot', parrot.name
978
+ assert_equal 'green', parrot.color
979
+ end
980
+
981
+ def test_first_or_initialize_with_no_parameters
982
+ parrot = Bird.where(:color => 'green').first_or_initialize
983
+ assert_kind_of Bird, parrot
984
+ assert !parrot.persisted?
985
+ assert !parrot.valid?
986
+ assert parrot.new_record?
987
+ assert_equal 'green', parrot.color
988
+ end
989
+
990
+ def test_first_or_initialize_with_block
991
+ parrot = Bird.where(:color => 'green').first_or_initialize { |bird| bird.name = 'parrot' }
992
+ assert_kind_of Bird, parrot
993
+ assert !parrot.persisted?
994
+ assert parrot.valid?
995
+ assert parrot.new_record?
996
+ assert_equal 'green', parrot.color
997
+ assert_equal 'parrot', parrot.name
998
+ end
999
+
1000
+ def test_explicit_create_scope
1001
+ hens = Bird.where(:name => 'hen')
1002
+ assert_equal 'hen', hens.new.name
1003
+
1004
+ hens = hens.create_with(:name => 'cock')
1005
+ assert_equal 'cock', hens.new.name
1006
+ end
1007
+
1008
+ def test_except
1009
+ relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1010
+ assert_equal [posts(:welcome)], relation.all
1011
+
1012
+ author_posts = relation.except(:order, :limit)
1013
+ assert_equal Post.where(:author_id => 1).all, author_posts.all
1014
+
1015
+ all_posts = relation.except(:where, :order, :limit)
1016
+ assert_equal Post.all, all_posts.all
1017
+ end
1018
+
1019
+ def test_extensions_with_except
1020
+ assert_equal 2, Topic.named_extension.order(:author_name).except(:order).two
1021
+ end
1022
+
1023
+ def test_only
1024
+ relation = Post.where(:author_id => 1).order('id ASC').limit(1)
1025
+ assert_equal [posts(:welcome)], relation.all
1026
+
1027
+ author_posts = relation.only(:where)
1028
+ assert_equal Post.where(:author_id => 1).all, author_posts.all
1029
+
1030
+ all_posts = relation.only(:limit)
1031
+ assert_equal Post.limit(1).all.first, all_posts.first
1032
+ end
1033
+
1034
+ def test_extensions_with_only
1035
+ assert_equal 2, Topic.named_extension.order(:author_name).only(:order).two
1036
+ end
1037
+
1038
+ def test_anonymous_extension
1039
+ relation = Post.where(:author_id => 1).order('id ASC').extending do
1040
+ def author
1041
+ 'lifo'
1042
+ end
1043
+ end
1044
+
1045
+ assert_equal "lifo", relation.author
1046
+ assert_equal "lifo", relation.limit(1).author
1047
+ end
1048
+
1049
+ def test_named_extension
1050
+ relation = Post.where(:author_id => 1).order('id ASC').extending(Post::NamedExtension)
1051
+ assert_equal "lifo", relation.author
1052
+ assert_equal "lifo", relation.limit(1).author
1053
+ end
1054
+
1055
+ def test_order_by_relation_attribute
1056
+ assert_equal Post.order(Post.arel_table[:title]).all, Post.order("title").all
1057
+ end
1058
+
1059
+ def test_order_with_find_with_order
1060
+ assert_equal 'zyke', CoolCar.order('name desc').find(:first, :order => 'id').name
1061
+ assert_equal 'zyke', FastCar.order('name desc').find(:first, :order => 'id').name
1062
+ end
1063
+
1064
+ def test_default_scope_order_with_scope_order
1065
+ assert_equal 'zyke', CoolCar.order_using_new_style.limit(1).first.name
1066
+ assert_equal 'zyke', CoolCar.order_using_old_style.limit(1).first.name
1067
+ assert_equal 'zyke', FastCar.order_using_new_style.limit(1).first.name
1068
+ assert_equal 'zyke', FastCar.order_using_old_style.limit(1).first.name
1069
+ end
1070
+
1071
+ def test_order_using_scoping
1072
+ car1 = CoolCar.order('id DESC').scoping do
1073
+ CoolCar.find(:first, :order => 'id asc')
1074
+ end
1075
+ assert_equal 'zyke', car1.name
1076
+
1077
+ car2 = FastCar.order('id DESC').scoping do
1078
+ FastCar.find(:first, :order => 'id asc')
1079
+ end
1080
+ assert_equal 'zyke', car2.name
1081
+ end
1082
+
1083
+ def test_unscoped_block_style
1084
+ assert_equal 'honda', CoolCar.unscoped { CoolCar.order_using_new_style.limit(1).first.name}
1085
+ assert_equal 'honda', CoolCar.unscoped { CoolCar.order_using_old_style.limit(1).first.name}
1086
+
1087
+ assert_equal 'honda', FastCar.unscoped { FastCar.order_using_new_style.limit(1).first.name}
1088
+ assert_equal 'honda', FastCar.unscoped { FastCar.order_using_old_style.limit(1).first.name}
1089
+ end
1090
+
1091
+ def test_intersection_with_array
1092
+ relation = Author.where(:name => "David")
1093
+ rails_author = relation.first
1094
+
1095
+ assert_equal [rails_author], [rails_author] & relation
1096
+ assert_equal [rails_author], relation & [rails_author]
1097
+ end
1098
+
1099
+ def test_removing_limit_with_options
1100
+ assert_not_equal 1, Post.limit(1).all(:limit => nil).count
1101
+ end
1102
+
1103
+ def test_primary_key
1104
+ assert_equal "id", Post.scoped.primary_key
1105
+ end
1106
+
1107
+ def test_eager_loading_with_conditions_on_joins
1108
+ scope = Post.includes(:comments)
1109
+
1110
+ # This references the comments table, and so it should cause the comments to be eager
1111
+ # loaded via a JOIN, rather than by subsequent queries.
1112
+ scope = scope.joins(
1113
+ Post.arel_table.create_join(
1114
+ Post.arel_table,
1115
+ Post.arel_table.create_on(Comment.arel_table[:id].eq(3))
1116
+ )
1117
+ )
1118
+
1119
+ assert scope.eager_loading?
1120
+ end
1121
+
1122
+ def test_ordering_with_extra_spaces
1123
+ assert_equal authors(:david), Author.order('id DESC , name DESC').last
1124
+ end
1125
+
1126
+ def test_update_all_with_joins
1127
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1128
+ count = comments.count
1129
+
1130
+ assert_equal count, comments.update_all(:post_id => posts(:thinking).id)
1131
+ assert_equal posts(:thinking), comments(:greetings).post
1132
+ end
1133
+
1134
+ def test_update_all_with_joins_and_limit
1135
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).limit(1)
1136
+ assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
1137
+ end
1138
+
1139
+ def test_update_all_with_joins_and_limit_and_order
1140
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('comments.id').limit(1)
1141
+ assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
1142
+ assert_equal posts(:thinking), comments(:greetings).post
1143
+ assert_equal posts(:welcome), comments(:more_greetings).post
1144
+ end
1145
+
1146
+ unless current_adapter?(:IBM_DBAdapter)
1147
+ #IBM_DB does not support offset on subselect of the update statement
1148
+ def test_update_all_with_joins_and_offset
1149
+ all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1150
+ count = all_comments.count
1151
+ comments = all_comments.offset(1)
1152
+
1153
+ assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1154
+ end
1155
+
1156
+ def test_update_all_with_joins_and_offset_and_order
1157
+ all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('posts.id', 'comments.id')
1158
+ count = all_comments.count
1159
+ comments = all_comments.offset(1)
1160
+
1161
+ assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1162
+ assert_equal posts(:thinking), comments(:more_greetings).post
1163
+ assert_equal posts(:welcome), comments(:greetings).post
1164
+ end
1165
+ end
1166
+
1167
+ def test_uniq
1168
+ tag1 = Tag.create(:name => 'Foo')
1169
+ tag2 = Tag.create(:name => 'Foo')
1170
+
1171
+ query = Tag.select(:name).where(:id => [tag1.id, tag2.id])
1172
+
1173
+ assert_equal ['Foo', 'Foo'], query.map(&:name)
1174
+ assert_sql(/DISTINCT/) do
1175
+ assert_equal ['Foo'], query.uniq.map(&:name)
1176
+ end
1177
+ assert_sql(/DISTINCT/) do
1178
+ assert_equal ['Foo'], query.uniq(true).map(&:name)
1179
+ end
1180
+ assert_equal ['Foo', 'Foo'], query.uniq(true).uniq(false).map(&:name)
1181
+ end
1182
+ end