ibm_db 2.5.6-x86-mingw32 → 2.5.7-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 (38) hide show
  1. data/CHANGES +6 -0
  2. data/README +1 -1
  3. data/ext/Makefile.nt32 +3 -3
  4. data/ext/Makefile.nt32.191 +212 -0
  5. data/ext/ibm_db.c +30 -5
  6. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +300 -108
  7. data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1 -1
  8. data/lib/mswin32/rb18x/ibm_db.so +0 -0
  9. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  10. data/test/cases/adapter_test.rb +25 -22
  11. data/test/cases/associations/belongs_to_associations_test.rb +245 -43
  12. data/test/cases/associations/cascaded_eager_loading_test.rb +28 -26
  13. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +60 -156
  14. data/test/cases/associations/join_model_test.rb +96 -146
  15. data/test/cases/attribute_methods_test.rb +98 -33
  16. data/test/cases/base_test.rb +525 -103
  17. data/test/cases/calculations_test.rb +92 -8
  18. data/test/cases/migration_test.rb +533 -207
  19. data/test/cases/persistence_test.rb +636 -0
  20. data/test/cases/query_cache_test.rb +242 -0
  21. data/test/cases/relations_test.rb +1019 -0
  22. data/test/cases/schema_dumper_test.rb +37 -17
  23. data/test/cases/transaction_callbacks_test.rb +300 -0
  24. data/test/cases/validations/uniqueness_validation_test.rb +38 -22
  25. data/test/cases/xml_serialization_test.rb +276 -0
  26. data/test/config.yml +154 -0
  27. data/test/connections/native_ibm_db/connection.rb +2 -0
  28. data/test/models/warehouse_thing.rb +4 -4
  29. data/test/schema/i5/ibm_db_specific_schema.rb +3 -1
  30. data/test/schema/ids/ibm_db_specific_schema.rb +3 -1
  31. data/test/schema/luw/ibm_db_specific_schema.rb +2 -0
  32. data/test/schema/schema.rb +174 -89
  33. data/test/schema/zOS/ibm_db_specific_schema.rb +3 -1
  34. metadata +10 -7
  35. data/test/cases/associations/eager_test.rb +0 -862
  36. data/test/cases/associations/has_many_through_associations_test.rb +0 -461
  37. data/test/cases/finder_test.rb +0 -1088
  38. data/test/cases/fixtures_test.rb +0 -684
@@ -0,0 +1,242 @@
1
+ require "cases/helper"
2
+ require 'models/topic'
3
+ require 'models/task'
4
+ require 'models/category'
5
+ require 'models/post'
6
+
7
+
8
+ class QueryCacheTest < ActiveRecord::TestCase
9
+ fixtures :tasks, :topics, :categories, :posts, :categories_posts
10
+
11
+ def setup
12
+ Task.connection.clear_query_cache
13
+ ActiveRecord::Base.connection.disable_query_cache!
14
+ end
15
+
16
+ def test_exceptional_middleware_clears_and_disables_cache_on_error
17
+ assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache off'
18
+
19
+ mw = ActiveRecord::QueryCache.new lambda { |env|
20
+ Task.find 1
21
+ Task.find 1
22
+ assert_equal 1, ActiveRecord::Base.connection.query_cache.length
23
+ raise "lol borked"
24
+ }
25
+ assert_raises(RuntimeError) { mw.call({}) }
26
+
27
+ assert_equal 0, ActiveRecord::Base.connection.query_cache.length
28
+ assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache off'
29
+ end
30
+
31
+ def test_exceptional_middleware_leaves_enabled_cache_alone
32
+ ActiveRecord::Base.connection.enable_query_cache!
33
+
34
+ mw = ActiveRecord::QueryCache.new lambda { |env|
35
+ raise "lol borked"
36
+ }
37
+ assert_raises(RuntimeError) { mw.call({}) }
38
+
39
+ assert ActiveRecord::Base.connection.query_cache_enabled, 'cache on'
40
+ end
41
+
42
+ def test_middleware_delegates
43
+ called = false
44
+ mw = ActiveRecord::QueryCache.new lambda { |env|
45
+ called = true
46
+ }
47
+ mw.call({})
48
+ assert called, 'middleware should delegate'
49
+ end
50
+
51
+ def test_middleware_caches
52
+ mw = ActiveRecord::QueryCache.new lambda { |env|
53
+ Task.find 1
54
+ Task.find 1
55
+ assert_equal 1, ActiveRecord::Base.connection.query_cache.length
56
+ }
57
+ mw.call({})
58
+ end
59
+
60
+ def test_cache_enabled_during_call
61
+ assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache off'
62
+
63
+ mw = ActiveRecord::QueryCache.new lambda { |env|
64
+ assert ActiveRecord::Base.connection.query_cache_enabled, 'cache on'
65
+ }
66
+ mw.call({})
67
+ end
68
+
69
+ def test_cache_on_during_body_write
70
+ streaming = Class.new do
71
+ def each
72
+ yield ActiveRecord::Base.connection.query_cache_enabled
73
+ end
74
+ end
75
+
76
+ mw = ActiveRecord::QueryCache.new lambda { |env|
77
+ [200, {}, streaming.new]
78
+ }
79
+ body = mw.call({}).last
80
+ body.each { |x| assert x, 'cache should be on' }
81
+ body.close
82
+ assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache disabled'
83
+ end
84
+
85
+ def test_cache_off_after_close
86
+ mw = ActiveRecord::QueryCache.new lambda { |env| }
87
+ body = mw.call({}).last
88
+
89
+ assert ActiveRecord::Base.connection.query_cache_enabled, 'cache enabled'
90
+ body.close
91
+ assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache disabled'
92
+ end
93
+
94
+ def test_cache_clear_after_close
95
+ mw = ActiveRecord::QueryCache.new lambda { |env|
96
+ Post.find(:first)
97
+ }
98
+ body = mw.call({}).last
99
+
100
+ assert !ActiveRecord::Base.connection.query_cache.empty?, 'cache not empty'
101
+ body.close
102
+ assert ActiveRecord::Base.connection.query_cache.empty?, 'cache should be empty'
103
+ end
104
+
105
+ def test_find_queries
106
+ assert_queries(ActiveRecord::IdentityMap.enabled? ? 1 : 2) { Task.find(1); Task.find(1) }
107
+ end
108
+
109
+ def test_find_queries_with_cache
110
+ Task.cache do
111
+ assert_queries(1) { Task.find(1); Task.find(1) }
112
+ end
113
+ end
114
+
115
+ def test_find_queries_with_cache_multi_record
116
+ Task.cache do
117
+ assert_queries(2) { Task.find(1); Task.find(1); Task.find(2) }
118
+ end
119
+ end
120
+
121
+ def test_count_queries_with_cache
122
+ Task.cache do
123
+ assert_queries(1) { Task.count; Task.count }
124
+ end
125
+ end
126
+
127
+ def test_query_cache_dups_results_correctly
128
+ Task.cache do
129
+ now = Time.now.utc
130
+ task = Task.find 1
131
+ assert_not_equal now, task.starting
132
+ task.starting = now
133
+ task.reload
134
+ assert_not_equal now, task.starting
135
+ end
136
+ end
137
+
138
+ def test_cache_is_flat
139
+ Task.cache do
140
+ Topic.columns # don't count this query
141
+ assert_queries(1) { Topic.find(1); Topic.find(1); }
142
+ end
143
+
144
+ ActiveRecord::Base.cache do
145
+ assert_queries(1) { Task.find(1); Task.find(1) }
146
+ end
147
+ end
148
+
149
+ def test_cache_does_not_wrap_string_results_in_arrays
150
+ require 'sqlite3/version' if current_adapter?(:SQLite3Adapter)
151
+
152
+ Task.cache do
153
+ # Oracle adapter returns count() as Fixnum or Float
154
+ if current_adapter?(:OracleAdapter,:IBM_DBAdapter)
155
+ assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
156
+ elsif current_adapter?(:SQLite3Adapter) && SQLite3::VERSION > '1.2.5' || current_adapter?(:Mysql2Adapter) || current_adapter?(:MysqlAdapter)
157
+ # Future versions of the sqlite3 adapter will return numeric
158
+ assert_instance_of Fixnum,
159
+ Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
160
+ else
161
+ assert_instance_of String, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ class QueryCacheExpiryTest < ActiveRecord::TestCase
168
+ fixtures :tasks, :posts, :categories, :categories_posts
169
+
170
+ def test_find
171
+ Task.connection.expects(:clear_query_cache).times(1)
172
+
173
+ assert !Task.connection.query_cache_enabled
174
+ Task.cache do
175
+ assert Task.connection.query_cache_enabled
176
+ Task.find(1)
177
+
178
+ Task.uncached do
179
+ assert !Task.connection.query_cache_enabled
180
+ Task.find(1)
181
+ end
182
+
183
+ assert Task.connection.query_cache_enabled
184
+ end
185
+ assert !Task.connection.query_cache_enabled
186
+ end
187
+
188
+ def test_update
189
+ Task.connection.expects(:clear_query_cache).times(2)
190
+
191
+ Task.cache do
192
+ task = Task.find(1)
193
+ task.starting = Time.now.utc
194
+ task.save!
195
+ end
196
+ end
197
+
198
+ def test_destroy
199
+ Task.connection.expects(:clear_query_cache).times(2)
200
+
201
+ Task.cache do
202
+ Task.find(1).destroy
203
+ end
204
+ end
205
+
206
+ def test_insert
207
+ ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
208
+
209
+ Task.cache do
210
+ Task.create!
211
+ end
212
+ end
213
+
214
+ def test_cache_is_expired_by_habtm_update
215
+ ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
216
+ ActiveRecord::Base.cache do
217
+ c = Category.find(:first)
218
+ p = Post.find(:first)
219
+ p.categories << c
220
+ end
221
+ end
222
+
223
+ def test_cache_is_expired_by_habtm_delete
224
+ ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
225
+ ActiveRecord::Base.cache do
226
+ p = Post.find(1)
227
+ assert p.categories.any?
228
+ p.categories.delete_all
229
+ end
230
+ end
231
+ end
232
+
233
+ class QueryCacheBodyProxyTest < ActiveRecord::TestCase
234
+
235
+ test "is polite to it's body and responds to it" do
236
+ body = Class.new(String) { def to_path; "/path"; end }.new
237
+ proxy = ActiveRecord::QueryCache::BodyProxy.new(nil, body)
238
+ assert proxy.respond_to?(:to_path)
239
+ assert_equal proxy.to_path, "/path"
240
+ end
241
+
242
+ end
@@ -0,0 +1,1019 @@
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
395
+ david = authors(:david)
396
+ author = Author.preload(:taggings).find_by_id(david.id)
397
+ expected_taggings = taggings(:welcome_general, :thinking_general)
398
+
399
+ assert_no_queries do
400
+ assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
401
+ end
402
+
403
+ authors = Author.scoped
404
+ assert_equal david, authors.find_by_id_and_name(david.id, david.name)
405
+ assert_equal david, authors.find_by_id_and_name!(david.id, david.name)
406
+ end
407
+
408
+ def test_dynamic_find_by_attributes_bang
409
+ author = Author.scoped.find_by_id!(authors(:david).id)
410
+ assert_equal "David", author.name
411
+
412
+ assert_raises(ActiveRecord::RecordNotFound) { Author.scoped.find_by_id_and_name!(20, 'invalid') }
413
+ end
414
+
415
+ def test_dynamic_find_all_by_attributes
416
+ authors = Author.scoped
417
+
418
+ davids = authors.find_all_by_name('David')
419
+ assert_kind_of Array, davids
420
+ assert_equal [authors(:david)], davids
421
+ end
422
+
423
+ def test_dynamic_find_or_initialize_by_attributes
424
+ authors = Author.scoped
425
+
426
+ lifo = authors.find_or_initialize_by_name('Lifo')
427
+ assert_equal "Lifo", lifo.name
428
+ assert !lifo.persisted?
429
+
430
+ assert_equal authors(:david), authors.find_or_initialize_by_name(:name => 'David')
431
+ end
432
+
433
+ def test_dynamic_find_or_create_by_attributes
434
+ authors = Author.scoped
435
+
436
+ lifo = authors.find_or_create_by_name('Lifo')
437
+ assert_equal "Lifo", lifo.name
438
+ assert lifo.persisted?
439
+
440
+ assert_equal authors(:david), authors.find_or_create_by_name(:name => 'David')
441
+ end
442
+
443
+ def test_find_id
444
+ authors = Author.scoped
445
+
446
+ david = authors.find(authors(:david).id)
447
+ assert_equal 'David', david.name
448
+
449
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') }
450
+ end
451
+
452
+ def test_find_ids
453
+ authors = Author.order('id ASC')
454
+
455
+ results = authors.find(authors(:david).id, authors(:mary).id)
456
+ assert_kind_of Array, results
457
+ assert_equal 2, results.size
458
+ assert_equal 'David', results[0].name
459
+ assert_equal 'Mary', results[1].name
460
+ assert_equal results, authors.find([authors(:david).id, authors(:mary).id])
461
+
462
+ assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') }
463
+ assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) }
464
+ end
465
+
466
+ def test_find_in_empty_array
467
+ authors = Author.scoped.where(:id => [])
468
+ assert_blank authors.all
469
+ end
470
+
471
+ def test_where_with_ar_object
472
+ author = Author.first
473
+ authors = Author.scoped.where(:id => author)
474
+ assert_equal 1, authors.all.length
475
+ end
476
+
477
+ def test_find_with_list_of_ar
478
+ author = Author.first
479
+ authors = Author.find([author])
480
+ assert_equal author, authors.first
481
+ end
482
+
483
+ class Mary < Author; end
484
+
485
+ def test_find_by_classname
486
+ Author.create!(:name => Mary.name)
487
+ assert_equal 1, Author.where(:name => Mary).size
488
+ end
489
+
490
+ def test_find_by_id_with_list_of_ar
491
+ author = Author.first
492
+ authors = Author.find_by_id([author])
493
+ assert_equal author, authors
494
+ end
495
+
496
+ def test_find_all_using_where_twice_should_or_the_relation
497
+ david = authors(:david)
498
+ relation = Author.unscoped
499
+ relation = relation.where(:name => david.name)
500
+ relation = relation.where(:name => 'Santiago')
501
+ relation = relation.where(:id => david.id)
502
+ assert_equal [], relation.all
503
+ end
504
+
505
+ def test_multi_where_ands_queries
506
+ relation = Author.unscoped
507
+ david = authors(:david)
508
+ sql = relation.where(:name => david.name).where(:name => 'Santiago').to_sql
509
+ assert_match('AND', sql)
510
+ end
511
+
512
+ def test_find_all_with_multiple_should_use_and
513
+ david = authors(:david)
514
+ relation = [
515
+ { :name => david.name },
516
+ { :name => 'Santiago' },
517
+ { :name => 'tenderlove' },
518
+ ].inject(Author.unscoped) do |memo, param|
519
+ memo.where(param)
520
+ end
521
+ assert_equal [], relation.all
522
+ end
523
+
524
+ def test_find_all_using_where_with_relation
525
+ david = authors(:david)
526
+ # switching the lines below would succeed in current rails
527
+ # assert_queries(2) {
528
+ assert_queries(1) {
529
+ relation = Author.where(:id => Author.where(:id => david.id))
530
+ assert_equal [david], relation.all
531
+ }
532
+ end
533
+
534
+ def test_find_all_using_where_with_relation_and_alternate_primary_key
535
+ cool_first = minivans(:cool_first)
536
+ # switching the lines below would succeed in current rails
537
+ # assert_queries(2) {
538
+ assert_queries(1) {
539
+ relation = Minivan.where(:minivan_id => Minivan.where(:name => cool_first.name))
540
+ assert_equal [cool_first], relation.all
541
+ }
542
+ end
543
+
544
+ def test_find_all_using_where_with_relation_does_not_alter_select_values
545
+ david = authors(:david)
546
+
547
+ subquery = Author.where(:id => david.id)
548
+
549
+ assert_queries(1) {
550
+ relation = Author.where(:id => subquery)
551
+ assert_equal [david], relation.all
552
+ }
553
+
554
+ assert_equal 0, subquery.select_values.size
555
+ end
556
+
557
+ def test_find_all_using_where_with_relation_with_joins
558
+ david = authors(:david)
559
+ assert_queries(1) {
560
+ relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
561
+ assert_equal [david], relation.all
562
+ }
563
+ end
564
+
565
+
566
+ def test_find_all_using_where_with_relation_with_select_to_build_subquery
567
+ david = authors(:david)
568
+ assert_queries(1) {
569
+ relation = Author.where(:name => Author.where(:id => david.id).select(:name))
570
+ assert_equal [david], relation.all
571
+ }
572
+ end
573
+
574
+ def test_exists
575
+ davids = Author.where(:name => 'David')
576
+ assert davids.exists?
577
+ assert davids.exists?(authors(:david).id)
578
+ assert ! davids.exists?(authors(:mary).id)
579
+ assert ! davids.exists?("42")
580
+ assert ! davids.exists?(42)
581
+
582
+ fake = Author.where(:name => 'fake author')
583
+ assert ! fake.exists?
584
+ assert ! fake.exists?(authors(:david).id)
585
+ end
586
+
587
+ def test_last
588
+ authors = Author.scoped
589
+ assert_equal authors(:bob), authors.last
590
+ end
591
+
592
+ def test_destroy_all
593
+ davids = Author.where(:name => 'David')
594
+
595
+ # Force load
596
+ assert_equal [authors(:david)], davids.to_a
597
+ assert davids.loaded?
598
+
599
+ assert_difference('Author.count', -1) { davids.destroy_all }
600
+
601
+ assert_equal [], davids.to_a
602
+ assert davids.loaded?
603
+ end
604
+
605
+ def test_delete_all
606
+ davids = Author.where(:name => 'David')
607
+
608
+ assert_difference('Author.count', -1) { davids.delete_all }
609
+ assert ! davids.loaded?
610
+ end
611
+
612
+ def test_delete_all_loaded
613
+ davids = Author.where(:name => 'David')
614
+
615
+ # Force load
616
+ assert_equal [authors(:david)], davids.to_a
617
+ assert davids.loaded?
618
+
619
+ assert_difference('Author.count', -1) { davids.delete_all }
620
+
621
+ assert_equal [], davids.to_a
622
+ assert davids.loaded?
623
+ end
624
+
625
+ def test_select_argument_error
626
+ assert_raises(ArgumentError) { Developer.select }
627
+ end
628
+
629
+ def test_relation_merging
630
+ devs = Developer.where("salary >= 80000").merge(Developer.limit(2)).merge(Developer.order('id ASC').where("id < 3"))
631
+ assert_equal [developers(:david), developers(:jamis)], devs.to_a
632
+
633
+ dev_with_count = Developer.limit(1).merge(Developer.order('id DESC')).merge(Developer.select('developers.*'))
634
+ assert_equal [developers(:poor_jamis)], dev_with_count.to_a
635
+ end
636
+
637
+ def test_relation_merging_with_eager_load
638
+ relations = []
639
+ relations << Post.order('comments.id DESC').merge(Post.eager_load(:last_comment)).merge(Post.scoped)
640
+ relations << Post.eager_load(:last_comment).merge(Post.order('comments.id DESC')).merge(Post.scoped)
641
+
642
+ relations.each do |posts|
643
+ post = posts.find { |p| p.id == 1 }
644
+ assert_equal Post.find(1).last_comment, post.last_comment
645
+ end
646
+ end
647
+
648
+ def test_relation_merging_with_locks
649
+ devs = Developer.lock.where("salary >= 80000").order("id DESC").merge(Developer.limit(2))
650
+ assert_present devs.locked
651
+ end
652
+
653
+ def test_relation_merging_with_preload
654
+ ActiveRecord::IdentityMap.without do
655
+ [Post.scoped.merge(Post.preload(:author)), Post.preload(:author).merge(Post.scoped)].each do |posts|
656
+ assert_queries(2) { assert posts.first.author }
657
+ end
658
+ end
659
+ end
660
+
661
+ def test_relation_merging_with_joins
662
+ comments = Comment.joins(:post).where(:body => 'Thank you for the welcome').merge(Post.where(:body => 'Such a lovely day'))
663
+ assert_equal 1, comments.count
664
+ end
665
+
666
+ def test_count
667
+ posts = Post.scoped
668
+
669
+ assert_equal 11, posts.count
670
+ assert_equal 11, posts.count(:all)
671
+ assert_equal 11, posts.count(:id)
672
+
673
+ assert_equal 1, posts.where('comments_count > 1').count
674
+ assert_equal 9, posts.where(:comments_count => 0).count
675
+ end
676
+
677
+ def test_count_with_distinct
678
+ posts = Post.scoped
679
+
680
+ assert_equal 3, posts.count(:comments_count, :distinct => true)
681
+ assert_equal 11, posts.count(:comments_count, :distinct => false)
682
+
683
+ assert_equal 3, posts.select(:comments_count).count(:distinct => true)
684
+ assert_equal 11, posts.select(:comments_count).count(:distinct => false)
685
+ end
686
+
687
+ def test_count_explicit_columns
688
+ Post.update_all(:comments_count => nil)
689
+ posts = Post.scoped
690
+
691
+ assert_equal [0], posts.select('comments_count').where('id is not null').group('id').order('id').count.values.uniq
692
+ assert_equal 0, posts.where('id is not null').select('comments_count').count
693
+
694
+ assert_equal 11, posts.select('comments_count').count('id')
695
+ assert_equal 0, posts.select('comments_count').count
696
+ assert_equal 0, posts.count(:comments_count)
697
+ assert_equal 0, posts.count('comments_count')
698
+ end
699
+
700
+ def test_multiple_selects
701
+ post = Post.scoped.select('comments_count').select('title').order("id ASC").first
702
+ assert_equal "Welcome to the weblog", post.title
703
+ assert_equal 2, post.comments_count
704
+ end
705
+
706
+ def test_size
707
+ posts = Post.scoped
708
+
709
+ assert_queries(1) { assert_equal 11, posts.size }
710
+ assert ! posts.loaded?
711
+
712
+ best_posts = posts.where(:comments_count => 0)
713
+ best_posts.to_a # force load
714
+ assert_no_queries { assert_equal 9, best_posts.size }
715
+ end
716
+
717
+ def test_size_with_limit
718
+ posts = Post.limit(10)
719
+
720
+ assert_queries(1) { assert_equal 10, posts.size }
721
+ assert ! posts.loaded?
722
+
723
+ best_posts = posts.where(:comments_count => 0)
724
+ best_posts.to_a # force load
725
+ assert_no_queries { assert_equal 9, best_posts.size }
726
+ end
727
+
728
+ def test_size_with_zero_limit
729
+ posts = Post.limit(0)
730
+
731
+ assert_no_queries { assert_equal 0, posts.size }
732
+ assert ! posts.loaded?
733
+
734
+ posts.to_a # force load
735
+ assert_no_queries { assert_equal 0, posts.size }
736
+ end
737
+
738
+ def test_empty_with_zero_limit
739
+ posts = Post.limit(0)
740
+
741
+ assert_no_queries { assert_equal true, posts.empty? }
742
+ assert ! posts.loaded?
743
+ end
744
+
745
+ def test_count_complex_chained_relations
746
+ posts = Post.select('comments_count').where('id is not null').group("author_id").where("comments_count > 0")
747
+
748
+ expected = { 1 => 2 }
749
+ assert_equal expected, posts.count
750
+ end
751
+
752
+ def test_empty
753
+ posts = Post.scoped
754
+
755
+ assert_queries(1) { assert_equal false, posts.empty? }
756
+ assert ! posts.loaded?
757
+
758
+ no_posts = posts.where(:title => "")
759
+ assert_queries(1) { assert_equal true, no_posts.empty? }
760
+ assert ! no_posts.loaded?
761
+
762
+ best_posts = posts.where(:comments_count => 0)
763
+ best_posts.to_a # force load
764
+ assert_no_queries { assert_equal false, best_posts.empty? }
765
+ end
766
+
767
+ def test_empty_complex_chained_relations
768
+ posts = Post.select("comments_count").where("id is not null").group("author_id").where("comments_count > 0")
769
+
770
+ assert_queries(1) { assert_equal false, posts.empty? }
771
+ assert ! posts.loaded?
772
+
773
+ no_posts = posts.where(:title => "")
774
+ assert_queries(1) { assert_equal true, no_posts.empty? }
775
+ assert ! no_posts.loaded?
776
+ end
777
+
778
+ def test_any
779
+ posts = Post.scoped
780
+
781
+ # This test was failing when run on its own (as opposed to running the entire suite).
782
+ # The second line in the assert_queries block was causing visit_Arel_Attributes_Attribute
783
+ # in Arel::Visitors::ToSql to trigger a SHOW TABLES query. Running that line here causes
784
+ # the SHOW TABLES result to be cached so we don't have to do it again in the block.
785
+ #
786
+ # This is obviously a rubbish fix but it's the best I can come up with for now...
787
+ posts.where(:id => nil).any?
788
+
789
+ assert_queries(3) do
790
+ assert posts.any? # Uses COUNT()
791
+ assert ! posts.where(:id => nil).any?
792
+
793
+ assert posts.any? {|p| p.id > 0 }
794
+ assert ! posts.any? {|p| p.id <= 0 }
795
+ end
796
+
797
+ assert posts.loaded?
798
+ end
799
+
800
+ def test_many
801
+ posts = Post.scoped
802
+
803
+ assert_queries(2) do
804
+ assert posts.many? # Uses COUNT()
805
+ assert posts.many? {|p| p.id > 0 }
806
+ assert ! posts.many? {|p| p.id < 2 }
807
+ end
808
+
809
+ assert posts.loaded?
810
+ end
811
+
812
+ def test_many_with_limits
813
+ posts = Post.scoped
814
+
815
+ assert posts.many?
816
+ assert ! posts.limit(1).many?
817
+ end
818
+
819
+ def test_build
820
+ posts = Post.scoped
821
+
822
+ post = posts.new
823
+ assert_kind_of Post, post
824
+ end
825
+
826
+ def test_scoped_build
827
+ posts = Post.where(:title => 'You told a lie')
828
+
829
+ post = posts.new
830
+ assert_kind_of Post, post
831
+ assert_equal 'You told a lie', post.title
832
+ end
833
+
834
+ def test_create
835
+ birds = Bird.scoped
836
+
837
+ sparrow = birds.create
838
+ assert_kind_of Bird, sparrow
839
+ assert !sparrow.persisted?
840
+
841
+ hen = birds.where(:name => 'hen').create
842
+ assert hen.persisted?
843
+ assert_equal 'hen', hen.name
844
+ end
845
+
846
+ def test_create_bang
847
+ birds = Bird.scoped
848
+
849
+ assert_raises(ActiveRecord::RecordInvalid) { birds.create! }
850
+
851
+ hen = birds.where(:name => 'hen').create!
852
+ assert_kind_of Bird, hen
853
+ assert hen.persisted?
854
+ assert_equal 'hen', hen.name
855
+ end
856
+
857
+ def test_explicit_create_scope
858
+ hens = Bird.where(:name => 'hen')
859
+ assert_equal 'hen', hens.new.name
860
+
861
+ hens = hens.create_with(:name => 'cock')
862
+ assert_equal 'cock', hens.new.name
863
+ end
864
+
865
+ def test_except
866
+ relation = Post.where(:author_id => 1).order('id ASC').limit(1)
867
+ assert_equal [posts(:welcome)], relation.all
868
+
869
+ author_posts = relation.except(:order, :limit)
870
+ assert_equal Post.where(:author_id => 1).all, author_posts.all
871
+
872
+ all_posts = relation.except(:where, :order, :limit)
873
+ assert_equal Post.all, all_posts.all
874
+ end
875
+
876
+ def test_extensions_with_except
877
+ assert_equal 2, Topic.named_extension.order(:author_name).except(:order).two
878
+ end
879
+
880
+ def test_only
881
+ relation = Post.where(:author_id => 1).order('id ASC').limit(1)
882
+ assert_equal [posts(:welcome)], relation.all
883
+
884
+ author_posts = relation.only(:where)
885
+ assert_equal Post.where(:author_id => 1).all, author_posts.all
886
+
887
+ all_posts = relation.only(:limit)
888
+ assert_equal Post.limit(1).all.first, all_posts.first
889
+ end
890
+
891
+ def test_extensions_with_only
892
+ assert_equal 2, Topic.named_extension.order(:author_name).only(:order).two
893
+ end
894
+
895
+ def test_anonymous_extension
896
+ relation = Post.where(:author_id => 1).order('id ASC').extending do
897
+ def author
898
+ 'lifo'
899
+ end
900
+ end
901
+
902
+ assert_equal "lifo", relation.author
903
+ assert_equal "lifo", relation.limit(1).author
904
+ end
905
+
906
+ def test_named_extension
907
+ relation = Post.where(:author_id => 1).order('id ASC').extending(Post::NamedExtension)
908
+ assert_equal "lifo", relation.author
909
+ assert_equal "lifo", relation.limit(1).author
910
+ end
911
+
912
+ def test_order_by_relation_attribute
913
+ assert_equal Post.order(Post.arel_table[:title]).all, Post.order("title").all
914
+ end
915
+
916
+ def test_order_with_find_with_order
917
+ assert_equal 'zyke', CoolCar.order('name desc').find(:first, :order => 'id').name
918
+ assert_equal 'zyke', FastCar.order('name desc').find(:first, :order => 'id').name
919
+ end
920
+
921
+ def test_default_scope_order_with_scope_order
922
+ assert_equal 'zyke', CoolCar.order_using_new_style.limit(1).first.name
923
+ assert_equal 'zyke', CoolCar.order_using_old_style.limit(1).first.name
924
+ assert_equal 'zyke', FastCar.order_using_new_style.limit(1).first.name
925
+ assert_equal 'zyke', FastCar.order_using_old_style.limit(1).first.name
926
+ end
927
+
928
+ def test_order_using_scoping
929
+ car1 = CoolCar.order('id DESC').scoping do
930
+ CoolCar.find(:first, :order => 'id asc')
931
+ end
932
+ assert_equal 'zyke', car1.name
933
+
934
+ car2 = FastCar.order('id DESC').scoping do
935
+ FastCar.find(:first, :order => 'id asc')
936
+ end
937
+ assert_equal 'zyke', car2.name
938
+ end
939
+
940
+ def test_unscoped_block_style
941
+ assert_equal 'honda', CoolCar.unscoped { CoolCar.order_using_new_style.limit(1).first.name}
942
+ assert_equal 'honda', CoolCar.unscoped { CoolCar.order_using_old_style.limit(1).first.name}
943
+
944
+ assert_equal 'honda', FastCar.unscoped { FastCar.order_using_new_style.limit(1).first.name}
945
+ assert_equal 'honda', FastCar.unscoped { FastCar.order_using_old_style.limit(1).first.name}
946
+ end
947
+
948
+ def test_intersection_with_array
949
+ relation = Author.where(:name => "David")
950
+ rails_author = relation.first
951
+
952
+ assert_equal [rails_author], [rails_author] & relation
953
+ assert_equal [rails_author], relation & [rails_author]
954
+ end
955
+
956
+ def test_removing_limit_with_options
957
+ assert_not_equal 1, Post.limit(1).all(:limit => nil).count
958
+ end
959
+
960
+ def test_primary_key
961
+ assert_equal "id", Post.scoped.primary_key
962
+ end
963
+
964
+ def test_eager_loading_with_conditions_on_joins
965
+ scope = Post.includes(:comments)
966
+
967
+ # This references the comments table, and so it should cause the comments to be eager
968
+ # loaded via a JOIN, rather than by subsequent queries.
969
+ scope = scope.joins(
970
+ Post.arel_table.create_join(
971
+ Post.arel_table,
972
+ Post.arel_table.create_on(Comment.arel_table[:id].eq(3))
973
+ )
974
+ )
975
+
976
+ assert scope.eager_loading?
977
+ end
978
+
979
+ def test_update_all_with_joins
980
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
981
+ count = comments.count
982
+
983
+ assert_equal count, comments.update_all(:post_id => posts(:thinking).id)
984
+ assert_equal posts(:thinking), comments(:greetings).post
985
+ end
986
+
987
+ def test_update_all_with_joins_and_limit
988
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).limit(1)
989
+ assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
990
+ end
991
+
992
+ def test_update_all_with_joins_and_limit_and_order
993
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('comments.id').limit(1)
994
+ assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
995
+ assert_equal posts(:thinking), comments(:greetings).post
996
+ assert_equal posts(:welcome), comments(:more_greetings).post
997
+ end
998
+
999
+ unless current_adapter?(:IBM_DBAdapter)
1000
+ #IBM_DB does not support offset on subselect of the update statement
1001
+ def test_update_all_with_joins_and_offset
1002
+ all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
1003
+ count = all_comments.count
1004
+ comments = all_comments.offset(1)
1005
+
1006
+ assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1007
+ end
1008
+
1009
+ def test_update_all_with_joins_and_offset_and_order
1010
+ all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('posts.id', 'comments.id')
1011
+ count = all_comments.count
1012
+ comments = all_comments.offset(1)
1013
+
1014
+ assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
1015
+ assert_equal posts(:thinking), comments(:more_greetings).post
1016
+ assert_equal posts(:welcome), comments(:greetings).post
1017
+ end
1018
+ end
1019
+ end