ibm_db 0.9.5 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/CHANGES +5 -0
  2. data/README +63 -97
  3. data/ext/ibm_db.c +20 -4
  4. data/ext/ruby_ibm_db.h +10 -0
  5. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +2 -4
  6. data/test/{adapter_test.rb → cases/adapter_test.rb} +39 -14
  7. data/test/cases/associations/cascaded_eager_loading_test.rb +113 -0
  8. data/test/{associations → cases/associations}/eager_test.rb +231 -65
  9. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +686 -0
  10. data/test/cases/associations/join_model_test.rb +797 -0
  11. data/test/{base_test.rb → cases/base_test.rb} +605 -385
  12. data/test/cases/calculations_test.rb +275 -0
  13. data/test/cases/finder_test.rb +885 -0
  14. data/test/cases/fixtures_test.rb +630 -0
  15. data/test/{migration_test.rb → cases/migration_test.rb} +530 -146
  16. data/test/cases/query_cache_test.rb +127 -0
  17. data/test/cases/validations_test.rb +1509 -0
  18. data/test/connections/native_ibm_db/connection.rb +1 -1
  19. data/test/models/warehouse_thing.rb +5 -0
  20. data/test/schema/i5/ibm_db_specific_schema.rb +133 -0
  21. data/test/schema/ids/ibm_db_specific_schema.rb +136 -0
  22. data/test/schema/luw/ibm_db_specific_schema.rb +133 -0
  23. data/test/schema/schema.rb +432 -0
  24. data/test/schema/zOS/ibm_db_specific_schema.rb +204 -0
  25. metadata +29 -33
  26. data/test/associations_test.rb +0 -2151
  27. data/test/fixtures/db_definitions/i5/ibm_db.drop.sql +0 -33
  28. data/test/fixtures/db_definitions/i5/ibm_db.sql +0 -236
  29. data/test/fixtures/db_definitions/i5/ibm_db2.drop.sql +0 -2
  30. data/test/fixtures/db_definitions/i5/ibm_db2.sql +0 -5
  31. data/test/fixtures/db_definitions/ids/ibm_db.drop.sql +0 -33
  32. data/test/fixtures/db_definitions/ids/ibm_db.sql +0 -237
  33. data/test/fixtures/db_definitions/ids/ibm_db2.drop.sql +0 -2
  34. data/test/fixtures/db_definitions/ids/ibm_db2.sql +0 -5
  35. data/test/fixtures/db_definitions/luw/ibm_db.drop.sql +0 -33
  36. data/test/fixtures/db_definitions/luw/ibm_db.sql +0 -236
  37. data/test/fixtures/db_definitions/luw/ibm_db2.drop.sql +0 -2
  38. data/test/fixtures/db_definitions/luw/ibm_db2.sql +0 -5
  39. data/test/fixtures/db_definitions/schema.rb +0 -361
  40. data/test/fixtures/db_definitions/zOS/ibm_db.drop.sql +0 -33
  41. data/test/fixtures/db_definitions/zOS/ibm_db.sql +0 -288
  42. data/test/fixtures/db_definitions/zOS/ibm_db2.drop.sql +0 -2
  43. data/test/fixtures/db_definitions/zOS/ibm_db2.sql +0 -7
  44. data/test/locking_test.rb +0 -282
@@ -1,17 +1,21 @@
1
- require 'abstract_unit'
2
- require 'fixtures/topic'
3
- require 'fixtures/reply'
4
- require 'fixtures/company'
5
- require 'fixtures/customer'
6
- require 'fixtures/developer'
7
- require 'fixtures/project'
8
- require 'fixtures/default'
9
- require 'fixtures/auto_id'
10
- require 'fixtures/column_name'
11
- require 'fixtures/subscriber'
12
- require 'fixtures/keyboard'
13
- require 'fixtures/post'
14
- require 'fixtures/minimalistic'
1
+ require "cases/helper"
2
+ require 'models/author'
3
+ require 'models/topic'
4
+ require 'models/reply'
5
+ require 'models/category'
6
+ require 'models/company'
7
+ require 'models/customer'
8
+ require 'models/developer'
9
+ require 'models/project'
10
+ require 'models/default'
11
+ require 'models/auto_id'
12
+ require 'models/column_name'
13
+ require 'models/subscriber'
14
+ require 'models/keyboard'
15
+ require 'models/post'
16
+ require 'models/comment'
17
+ require 'models/minimalistic'
18
+ require 'models/warehouse_thing'
15
19
  require 'rexml/document'
16
20
 
17
21
  class Category < ActiveRecord::Base; end
@@ -64,15 +68,15 @@ class Task < ActiveRecord::Base
64
68
  attr_protected :starting
65
69
  end
66
70
 
67
- class TopicWithProtectedContentAndAccessibleAuthorName < ActiveRecord::Base
68
- self.table_name = 'topics'
71
+ class TopicWithProtectedContentAndAccessibleAuthorName < ActiveRecord::Base
72
+ self.table_name = 'topics'
69
73
  attr_accessible :author_name
70
74
  attr_protected :content
71
75
  end
72
76
 
73
- class IBMDBBasicsTest < Test::Unit::TestCase
74
- fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics
75
-
77
+ class BasicsTest < ActiveRecord::TestCase
78
+ fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, :warehouse_things, :authors
79
+
76
80
  def test_table_exists
77
81
  assert !NonExistentTable.table_exists?
78
82
  assert Topic.table_exists?
@@ -86,7 +90,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
86
90
  assert_equal("Jason", topic.author_name)
87
91
  assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
88
92
  end
89
-
93
+
90
94
  def test_integers_as_nil
91
95
  test = AutoId.create('value' => '')
92
96
  assert_nil AutoId.find(test.id).value
@@ -97,7 +101,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
97
101
  t.title = "Budget"
98
102
  t.author_name = "Jason"
99
103
  end
100
-
104
+
101
105
  assert_equal("Budget", topic.title)
102
106
  assert_equal("Jason", topic.author_name)
103
107
  end
@@ -120,44 +124,63 @@ class IBMDBBasicsTest < Test::Unit::TestCase
120
124
  topic = Topic.new
121
125
  topic.content = %w( one two three )
122
126
  topic.save
123
-
127
+
124
128
  assert_equal(%w( one two three ), Topic.find(topic.id).content)
125
129
  end
126
-
130
+
131
+ def test_read_attributes_before_type_cast
132
+ category = Category.new({:name=>"Test categoty", :type => nil})
133
+ category_attrs = {"name"=>"Test categoty", "type" => nil}
134
+ assert_equal category_attrs , category.attributes_before_type_cast
135
+ end
136
+
137
+ if current_adapter?(:MysqlAdapter)
138
+ def test_read_attributes_before_type_cast_on_boolean
139
+ bool = Booleantest.create({ "value" => false })
140
+ assert_equal 0, bool.attributes_before_type_cast["value"]
141
+ end
142
+ end
143
+
144
+ def test_read_attributes_before_type_cast_on_datetime
145
+ developer = Developer.find(:first)
146
+ assert_equal developer.created_at.to_s(:db) , developer.attributes_before_type_cast["created_at"]
147
+ end
148
+
127
149
  def test_hash_content
128
150
  topic = Topic.new
129
151
  topic.content = { "one" => 1, "two" => 2 }
130
152
  topic.save
131
-
153
+
132
154
  assert_equal 2, Topic.find(topic.id).content["two"]
133
155
 
156
+ topic.content_will_change!
134
157
  topic.content["three"] = 3
135
158
  topic.save
136
-
159
+
137
160
  assert_equal 3, Topic.find(topic.id).content["three"]
138
161
  end
139
162
 
140
163
  def test_update_array_content
141
164
  topic = Topic.new
142
165
  topic.content = %w( one two three )
143
-
166
+
144
167
  topic.content.push "four"
145
168
  assert_equal(%w( one two three four ), topic.content)
146
-
169
+
147
170
  topic.save
148
171
 
149
172
  topic = Topic.find(topic.id)
150
173
  topic.content << "five"
151
174
  assert_equal(%w( one two three four five ), topic.content)
152
175
  end
153
-
176
+
154
177
  def test_case_sensitive_attributes_hash
155
178
  # DB2 is not case-sensitive
156
179
  return true if current_adapter?(:DB2Adapter, :IBM_DBAdapter)
157
-
180
+
158
181
  assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.find(:first).attributes
159
182
  end
160
-
183
+
161
184
  def test_create
162
185
  topic = Topic.new
163
186
  topic.title = "New Topic"
@@ -173,7 +196,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
173
196
  reply = Reply.new
174
197
  assert_raise(ActiveRecord::RecordInvalid) { reply.save! }
175
198
  end
176
-
199
+
177
200
  def test_save_null_string_attributes
178
201
  topic = Topic.find(1)
179
202
  topic.attributes = { "title" => "null", "author_name" => "null" }
@@ -182,7 +205,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
182
205
  assert_equal("null", topic.title)
183
206
  assert_equal("null", topic.author_name)
184
207
  end
185
-
208
+
186
209
  def test_save_nil_string_attributes
187
210
  topic = Topic.find(1)
188
211
  topic.title = nil
@@ -190,23 +213,23 @@ class IBMDBBasicsTest < Test::Unit::TestCase
190
213
  topic.reload
191
214
  assert_nil topic.title
192
215
  end
193
-
216
+
194
217
  def test_save_for_record_with_only_primary_key
195
218
  minimalistic = Minimalistic.new
196
219
  assert_nothing_raised { minimalistic.save }
197
220
  end
198
-
221
+
199
222
  def test_save_for_record_with_only_primary_key_that_is_provided
200
223
  assert_nothing_raised { Minimalistic.create!(:id => 2) }
201
224
  end
202
-
225
+
203
226
  def test_hashes_not_mangled
204
227
  new_topic = { :title => "New Topic" }
205
228
  new_topic_values = { :title => "AnotherTopic" }
206
-
229
+
207
230
  topic = Topic.new(new_topic)
208
231
  assert_equal new_topic[:title], topic.title
209
-
232
+
210
233
  topic.attributes= new_topic_values
211
234
  assert_equal new_topic_values[:title], topic.title
212
235
  end
@@ -216,20 +239,41 @@ class IBMDBBasicsTest < Test::Unit::TestCase
216
239
  assert_equal 2, topics.size
217
240
  assert_equal "first", topics.first.title
218
241
  end
219
-
242
+
220
243
  def test_create_columns_not_equal_attributes
221
244
  topic = Topic.new
222
245
  topic.title = 'Another New Topic'
223
246
  topic.send :write_attribute, 'does_not_exist', 'test'
224
247
  assert_nothing_raised { topic.save }
225
248
  end
226
-
249
+
227
250
  def test_create_through_factory
228
251
  topic = Topic.create("title" => "New Topic")
229
252
  topicReloaded = Topic.find(topic.id)
230
253
  assert_equal(topic, topicReloaded)
254
+ end
255
+
256
+ def test_create_through_factory_with_block
257
+ topic = Topic.create("title" => "New Topic") do |t|
258
+ t.author_name = "David"
259
+ end
260
+ topicReloaded = Topic.find(topic.id)
261
+ assert_equal("New Topic", topic.title)
262
+ assert_equal("David", topic.author_name)
231
263
  end
232
-
264
+
265
+ def test_create_many_through_factory_with_block
266
+ topics = Topic.create([ { "title" => "first" }, { "title" => "second" }]) do |t|
267
+ t.author_name = "David"
268
+ end
269
+ assert_equal 2, topics.size
270
+ topic1, topic2 = Topic.find(topics[0].id), Topic.find(topics[1].id)
271
+ assert_equal "first", topic1.title
272
+ assert_equal "David", topic1.author_name
273
+ assert_equal "second", topic2.title
274
+ assert_equal "David", topic2.author_name
275
+ end
276
+
233
277
  def test_update
234
278
  topic = Topic.new
235
279
  topic.title = "Another New Topic"
@@ -237,7 +281,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
237
281
  topic.save
238
282
  topicReloaded = Topic.find(topic.id)
239
283
  assert_equal("Another New Topic", topicReloaded.title)
240
-
284
+
241
285
  topicReloaded.title = "Updated topic"
242
286
  topicReloaded.save
243
287
 
@@ -245,7 +289,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
245
289
 
246
290
  assert_equal("Updated topic", topicReloadedAgain.title)
247
291
  end
248
-
292
+
249
293
  def test_update_columns_not_equal_attributes
250
294
  topic = Topic.new
251
295
  topic.title = "Still another topic"
@@ -256,7 +300,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
256
300
  topicReloaded.send :write_attribute, 'does_not_exist', 'test'
257
301
  assert_nothing_raised { topicReloaded.save }
258
302
  end
259
-
303
+
260
304
  def test_update_for_record_with_only_primary_key
261
305
  minimalistic = minimalistics(:first)
262
306
  assert_nothing_raised { minimalistic.save }
@@ -266,21 +310,21 @@ class IBMDBBasicsTest < Test::Unit::TestCase
266
310
  topic = Topic.new
267
311
  topic.send(:write_attribute, :title, "Still another topic")
268
312
  assert_equal "Still another topic", topic.title
269
-
313
+
270
314
  topic.send(:write_attribute, "title", "Still another topic: part 2")
271
315
  assert_equal "Still another topic: part 2", topic.title
272
316
  end
273
-
317
+
274
318
  def test_read_attribute
275
319
  topic = Topic.new
276
320
  topic.title = "Don't change the topic"
277
321
  assert_equal "Don't change the topic", topic.send(:read_attribute, "title")
278
322
  assert_equal "Don't change the topic", topic["title"]
279
-
323
+
280
324
  assert_equal "Don't change the topic", topic.send(:read_attribute, :title)
281
325
  assert_equal "Don't change the topic", topic[:title]
282
326
  end
283
-
327
+
284
328
  def test_read_attribute_when_false
285
329
  topic = topics(:first)
286
330
  topic.approved = false
@@ -288,7 +332,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
288
332
  topic.approved = "false"
289
333
  assert !topic.approved?, "approved should be false"
290
334
  end
291
-
335
+
292
336
  def test_read_attribute_when_true
293
337
  topic = topics(:first)
294
338
  topic.approved = true
@@ -296,7 +340,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
296
340
  topic.approved = "true"
297
341
  assert topic.approved?, "approved should be true"
298
342
  end
299
-
343
+
300
344
  def test_read_write_boolean_attribute
301
345
  topic = Topic.new
302
346
  # puts ""
@@ -347,7 +391,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
347
391
  assert_equal true, Topic.new(:approved => value).approved?
348
392
  end
349
393
  end
350
-
394
+
351
395
  def test_query_attribute_with_custom_fields
352
396
  object = Company.find_by_sql(<<-SQL).first
353
397
  SELECT c1.*, c2.ruby_type as string_value, c2.rating as int_value
@@ -355,63 +399,63 @@ class IBMDBBasicsTest < Test::Unit::TestCase
355
399
  WHERE c1.firm_id = c2.id
356
400
  AND c1.id = 2
357
401
  SQL
358
-
402
+
359
403
  assert_equal "Firm", object.string_value
360
404
  assert object.string_value?
361
-
405
+
362
406
  object.string_value = " "
363
407
  assert !object.string_value?
364
-
408
+
365
409
  assert_equal 1, object.int_value.to_i
366
410
  assert object.int_value?
367
-
411
+
368
412
  object.int_value = "0"
369
413
  assert !object.int_value?
370
414
  end
371
-
372
-
415
+
416
+
373
417
  def test_reader_for_invalid_column_names
374
418
  Topic.send(:define_read_method, "mumub-jumbo".to_sym, "mumub-jumbo", nil)
375
419
  assert !Topic.generated_methods.include?("mumub-jumbo")
376
420
  end
377
-
421
+
378
422
  def test_non_attribute_access_and_assignment
379
423
  topic = Topic.new
380
424
  assert !topic.respond_to?("mumbo")
381
425
  assert_raises(NoMethodError) { topic.mumbo }
382
426
  assert_raises(NoMethodError) { topic.mumbo = 5 }
383
427
  end
384
-
428
+
385
429
  def test_preserving_date_objects
386
430
  # SQL Server doesn't have a separate column type just for dates, so all are returned as time
387
431
  return true if current_adapter?(:SQLServerAdapter)
388
-
432
+
389
433
  if current_adapter?(:SybaseAdapter, :OracleAdapter)
390
434
  # Sybase ctlib does not (yet?) support the date type; use datetime instead.
391
435
  # Oracle treats all dates/times as Time.
392
436
  assert_kind_of(
393
- Time, Topic.find(1).last_read,
437
+ Time, Topic.find(1).last_read,
394
438
  "The last_read attribute should be of the Time class"
395
439
  )
396
440
  else
397
441
  assert_kind_of(
398
- Date, Topic.find(1).last_read,
442
+ Date, Topic.find(1).last_read,
399
443
  "The last_read attribute should be of the Date class"
400
444
  )
401
445
  end
402
446
  end
403
-
447
+
404
448
  def test_preserving_time_objects
405
449
  assert_kind_of(
406
- Time, Topic.find(1).bonus_time,
450
+ Time, Topic.find(1).bonus_time,
407
451
  "The bonus_time attribute should be of the Time class"
408
452
  )
409
-
453
+
410
454
  assert_kind_of(
411
- Time, Topic.find(1).written_on,
455
+ Time, Topic.find(1).written_on,
412
456
  "The written_on attribute should be of the Time class"
413
457
  )
414
-
458
+
415
459
  # For adapters which support microsecond resolution.
416
460
  if current_adapter?(:PostgreSQLAdapter)
417
461
  assert_equal 11, Topic.find(1).written_on.sec
@@ -426,20 +470,20 @@ class IBMDBBasicsTest < Test::Unit::TestCase
426
470
  topic.send(:approved=, true)
427
471
  assert topic.instance_variable_get("@custom_approved")
428
472
  end
429
-
473
+
430
474
  def test_destroy
431
475
  topic = Topic.find(1)
432
476
  assert_equal topic, topic.destroy, 'topic.destroy did not return self'
433
477
  assert topic.frozen?, 'topic not frozen after destroy'
434
478
  assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
435
479
  end
436
-
480
+
437
481
  def test_record_not_found_exception
438
482
  assert_raises(ActiveRecord::RecordNotFound) { topicReloaded = Topic.find(99999) }
439
483
  end
440
484
 
441
485
  def test_initialize_with_attributes
442
- topic = Topic.new({
486
+ topic = Topic.new({
443
487
  "title" => "initialized from attributes", "written_on" => "2003-12-12 23:23"
444
488
  })
445
489
 
@@ -448,7 +492,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
448
492
 
449
493
  def test_initialize_with_invalid_attribute
450
494
  begin
451
- topic = Topic.new({ "title" => "test",
495
+ topic = Topic.new({ "title" => "test",
452
496
  "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"})
453
497
  rescue ActiveRecord::MultiparameterAssignmentErrors => ex
454
498
  assert_equal(1, ex.errors.size)
@@ -457,8 +501,8 @@ class IBMDBBasicsTest < Test::Unit::TestCase
457
501
  end
458
502
 
459
503
  def test_load
460
- topics = Topic.find(:all, :order => 'id')
461
- assert_equal(2, topics.size)
504
+ topics = Topic.find(:all, :order => 'id')
505
+ assert_equal(4, topics.size)
462
506
  assert_equal(topics(:first).title, topics.first.title)
463
507
  end
464
508
 
@@ -468,12 +512,12 @@ class IBMDBBasicsTest < Test::Unit::TestCase
468
512
  assert_equal(1, topics.size)
469
513
  assert_equal(topics(:second).title, topics.first.title)
470
514
  end
471
-
515
+
472
516
  def test_table_name_guesses
473
517
  classes = [Category, Smarts, CreditCard, CreditCard::PinNumber, CreditCard::PinNumber::CvvCode, CreditCard::SubPinNumber, CreditCard::Brand, MasterCreditCard]
474
-
518
+
475
519
  assert_equal "topics", Topic.table_name
476
-
520
+
477
521
  assert_equal "categories", Category.table_name
478
522
  assert_equal "smarts", Smarts.table_name
479
523
  assert_equal "credit_cards", CreditCard.table_name
@@ -482,10 +526,10 @@ class IBMDBBasicsTest < Test::Unit::TestCase
482
526
  assert_equal "credit_card_pin_numbers", CreditCard::SubPinNumber.table_name
483
527
  assert_equal "categories", CreditCard::Brand.table_name
484
528
  assert_equal "master_credit_cards", MasterCreditCard.table_name
485
-
529
+
486
530
  ActiveRecord::Base.pluralize_table_names = false
487
531
  classes.each(&:reset_table_name)
488
-
532
+
489
533
  assert_equal "category", Category.table_name
490
534
  assert_equal "smarts", Smarts.table_name
491
535
  assert_equal "credit_card", CreditCard.table_name
@@ -494,10 +538,10 @@ class IBMDBBasicsTest < Test::Unit::TestCase
494
538
  assert_equal "credit_card_pin_number", CreditCard::SubPinNumber.table_name
495
539
  assert_equal "category", CreditCard::Brand.table_name
496
540
  assert_equal "master_credit_card", MasterCreditCard.table_name
497
-
541
+
498
542
  ActiveRecord::Base.pluralize_table_names = true
499
543
  classes.each(&:reset_table_name)
500
-
544
+
501
545
  ActiveRecord::Base.table_name_prefix = "test_"
502
546
  Category.reset_table_name
503
547
  assert_equal "test_categories", Category.table_name
@@ -510,7 +554,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
510
554
  ActiveRecord::Base.table_name_suffix = ""
511
555
  Category.reset_table_name
512
556
  assert_equal "categories", Category.table_name
513
-
557
+
514
558
  ActiveRecord::Base.pluralize_table_names = false
515
559
  ActiveRecord::Base.table_name_prefix = "test_"
516
560
  Category.reset_table_name
@@ -524,29 +568,31 @@ class IBMDBBasicsTest < Test::Unit::TestCase
524
568
  ActiveRecord::Base.table_name_suffix = ""
525
569
  Category.reset_table_name
526
570
  assert_equal "category", Category.table_name
527
-
571
+
528
572
  ActiveRecord::Base.pluralize_table_names = true
529
573
  classes.each(&:reset_table_name)
530
574
  end
531
575
 
532
576
  def test_destroy_all
533
- assert_equal 2, Topic.count
534
-
535
- Topic.destroy_all "author_name = 'Mary'"
536
- assert_equal 1, Topic.count
577
+ original_count = Topic.count
578
+ topics_by_mary = Topic.count(:conditions => mary = "author_name = 'Mary'")
579
+
580
+ Topic.destroy_all mary
581
+ assert_equal original_count - topics_by_mary, Topic.count
537
582
  end
538
-
583
+
539
584
  def test_destroy_many
540
585
  assert_equal 3, Client.count
541
586
  Client.destroy([2, 3])
542
587
  assert_equal 1, Client.count
543
588
  end
544
-
589
+
545
590
  def test_delete_many
546
- Topic.delete([1, 2])
547
- assert_equal 0, Topic.count
591
+ original_count = Topic.count
592
+ Topic.delete(deleting = [1, 2])
593
+ assert_equal original_count - deleting.size, Topic.count
548
594
  end
549
-
595
+
550
596
  def test_boolean_attributes
551
597
  assert ! Topic.find(1).approved?
552
598
  assert Topic.find(2).approved?
@@ -555,7 +601,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
555
601
  def test_increment_counter
556
602
  Topic.increment_counter("replies_count", 1)
557
603
  assert_equal 2, Topic.find(1).replies_count
558
-
604
+
559
605
  Topic.increment_counter("replies_count", 1)
560
606
  assert_equal 3, Topic.find(1).replies_count
561
607
  end
@@ -563,58 +609,72 @@ class IBMDBBasicsTest < Test::Unit::TestCase
563
609
  def test_decrement_counter
564
610
  Topic.decrement_counter("replies_count", 2)
565
611
  assert_equal -1, Topic.find(2).replies_count
566
-
612
+
567
613
  Topic.decrement_counter("replies_count", 2)
568
614
  assert_equal -2, Topic.find(2).replies_count
569
615
  end
570
-
616
+
571
617
  def test_update_all
572
- assert_equal 2, Topic.update_all("content = 'bulk updated!'")
618
+ assert_equal Topic.count, Topic.update_all("content = 'bulk updated!'")
573
619
  assert_equal "bulk updated!", Topic.find(1).content
574
620
  assert_equal "bulk updated!", Topic.find(2).content
575
-
576
- assert_equal 2, Topic.update_all(['content = ?', 'bulk updated again!'])
621
+
622
+ assert_equal Topic.count, Topic.update_all(['content = ?', 'bulk updated again!'])
577
623
  assert_equal "bulk updated again!", Topic.find(1).content
578
624
  assert_equal "bulk updated again!", Topic.find(2).content
579
-
580
- assert_equal 2, Topic.update_all(['content = ?', nil])
625
+
626
+ assert_equal Topic.count, Topic.update_all(['content = ?', nil])
581
627
  assert_nil Topic.find(1).content
582
628
  end
583
-
629
+
584
630
  def test_update_all_with_hash
585
631
  assert_not_nil Topic.find(1).last_read
586
- assert_equal 2, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil)
632
+ assert_equal Topic.count, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil)
587
633
  assert_equal "bulk updated with hash!", Topic.find(1).content
588
634
  assert_equal "bulk updated with hash!", Topic.find(2).content
589
635
  assert_nil Topic.find(1).last_read
590
636
  assert_nil Topic.find(2).last_read
591
637
  end
592
-
638
+
639
+ def test_update_all_with_non_standard_table_name
640
+ assert_equal 1, WarehouseThing.update_all(['value = ?', 0], ['id = ?', 1])
641
+ assert_equal 0, WarehouseThing.find(1).value
642
+ end
643
+
593
644
  if current_adapter?(:MysqlAdapter)
594
645
  def test_update_all_with_order_and_limit
595
646
  assert_equal 1, Topic.update_all("content = 'bulk updated!'", nil, :limit => 1, :order => 'id DESC')
596
647
  end
597
648
  end
598
-
649
+
650
+ def test_update_all_ignores_order_limit_from_association
651
+ author = Author.find(1)
652
+ assert_nothing_raised do
653
+ assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all("body = 'bulk update!'")
654
+ end
655
+ end
656
+
599
657
  def test_update_many
600
658
  topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } }
601
659
  updated = Topic.update(topic_data.keys, topic_data.values)
602
-
660
+
603
661
  assert_equal 2, updated.size
604
662
  assert_equal "1 updated", Topic.find(1).content
605
663
  assert_equal "2 updated", Topic.find(2).content
606
664
  end
607
-
665
+
608
666
  def test_delete_all
609
- assert_equal 2, Topic.delete_all
667
+ assert Topic.count > 0
668
+
669
+ assert_equal Topic.count, Topic.delete_all
610
670
  end
611
-
671
+
612
672
  def test_update_by_condition
613
673
  Topic.update_all "content = 'bulk updated!'", ["approved = ?", true]
614
674
  assert_equal "Have a nice day", Topic.find(1).content
615
675
  assert_equal "bulk updated!", Topic.find(2).content
616
676
  end
617
-
677
+
618
678
  def test_attribute_present
619
679
  t = Topic.new
620
680
  t.title = "hello there!"
@@ -634,11 +694,11 @@ class IBMDBBasicsTest < Test::Unit::TestCase
634
694
  assert_equal "Firm", ActiveRecord::Base.class_name("firms")
635
695
  assert_equal "Category", ActiveRecord::Base.class_name("categories")
636
696
  assert_equal "AccountHolder", ActiveRecord::Base.class_name("account_holder")
637
-
697
+
638
698
  ActiveRecord::Base.pluralize_table_names = false
639
699
  assert_equal "Firms", ActiveRecord::Base.class_name( "firms" )
640
700
  ActiveRecord::Base.pluralize_table_names = true
641
-
701
+
642
702
  ActiveRecord::Base.table_name_prefix = "test_"
643
703
  assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms" )
644
704
  ActiveRecord::Base.table_name_suffix = "_tests"
@@ -662,12 +722,12 @@ class IBMDBBasicsTest < Test::Unit::TestCase
662
722
  assert_nil topic.last_read
663
723
 
664
724
  topic.save
665
-
725
+
666
726
  topic = Topic.find(topic.id)
667
727
  assert topic.approved?
668
728
  assert_nil topic.last_read
669
-
670
- # Oracle has some funky default handling, so it requires a bit of
729
+
730
+ # Oracle has some funky default handling, so it requires a bit of
671
731
  # extra testing. See ticket #2788.
672
732
  if current_adapter?(:OracleAdapter)
673
733
  test = TestOracleDefault.new
@@ -676,7 +736,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
676
736
  assert_equal 3, test.test_int
677
737
  end
678
738
  end
679
-
739
+
680
740
  # Oracle, SQLServer, and Sybase do not have a TIME datatype.
681
741
  unless current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
682
742
  def test_utc_as_time_zone
@@ -687,7 +747,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
687
747
  assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
688
748
  Topic.default_timezone = :local
689
749
  end
690
-
750
+
691
751
  def test_utc_as_time_zone_and_new
692
752
  Topic.default_timezone = :utc
693
753
  attributes = { "bonus_time(1i)"=>"2000",
@@ -701,17 +761,17 @@ class IBMDBBasicsTest < Test::Unit::TestCase
701
761
  Topic.default_timezone = :local
702
762
  end
703
763
  end
704
-
764
+
705
765
  def test_default_values_on_empty_strings
706
766
  topic = Topic.new
707
767
  topic.approved = nil
708
768
  topic.last_read = nil
709
-
769
+
710
770
  topic.save
711
-
771
+
712
772
  topic = Topic.find(topic.id)
713
773
  assert_nil topic.last_read
714
-
774
+
715
775
  # Sybase adapter does not allow nulls in boolean columns
716
776
  if current_adapter?(:SybaseAdapter)
717
777
  assert topic.approved == false
@@ -719,7 +779,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
719
779
  assert_nil topic.approved
720
780
  end
721
781
  end
722
-
782
+
723
783
  def test_equality
724
784
  assert_equal Topic.find(1), Topic.find(2).topic
725
785
  end
@@ -743,14 +803,14 @@ class IBMDBBasicsTest < Test::Unit::TestCase
743
803
  client.destroy
744
804
  assert client.frozen?
745
805
  assert_kind_of Firm, client.firm
746
- assert_raises(TypeError) { client.name = "something else" }
806
+ assert_raises(ActiveSupport::FrozenObjectError) { client.name = "something else" }
747
807
  end
748
808
 
749
809
  def test_update_attribute
750
810
  assert !Topic.find(1).approved?
751
811
  Topic.find(1).update_attribute("approved", true)
752
812
  assert Topic.find(1).approved?
753
-
813
+
754
814
  Topic.find(1).update_attribute(:approved, false)
755
815
  assert !Topic.find(1).approved?
756
816
  end
@@ -764,7 +824,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
764
824
  topic.reload
765
825
  assert topic.approved?
766
826
  assert_equal "The First Topic Updated", topic.title
767
-
827
+
768
828
  topic.update_attributes(:approved => false, :title => "The First Topic")
769
829
  topic.reload
770
830
  assert !topic.approved?
@@ -773,17 +833,17 @@ class IBMDBBasicsTest < Test::Unit::TestCase
773
833
 
774
834
  def test_update_attributes!
775
835
  reply = Reply.find(2)
776
- assert_equal "The Second Topic's of the day", reply.title
836
+ assert_equal "The Second Topic of the day", reply.title
777
837
  assert_equal "Have a nice day", reply.content
778
838
 
779
- reply.update_attributes!("title" => "The Second Topic's of the day updated", "content" => "Have a nice evening")
839
+ reply.update_attributes!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening")
780
840
  reply.reload
781
- assert_equal "The Second Topic's of the day updated", reply.title
841
+ assert_equal "The Second Topic of the day updated", reply.title
782
842
  assert_equal "Have a nice evening", reply.content
783
843
 
784
- reply.update_attributes!(:title => "The Second Topic's of the day", :content => "Have a nice day")
844
+ reply.update_attributes!(:title => "The Second Topic of the day", :content => "Have a nice day")
785
845
  reply.reload
786
- assert_equal "The Second Topic's of the day", reply.title
846
+ assert_equal "The Second Topic of the day", reply.title
787
847
  assert_equal "Have a nice day", reply.content
788
848
 
789
849
  assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(:title => nil, :content => "Have a nice evening") }
@@ -803,26 +863,26 @@ class IBMDBBasicsTest < Test::Unit::TestCase
803
863
 
804
864
  def test_mass_assignment_protection_against_class_attribute_writers
805
865
  [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :colorize_logging,
806
- :default_timezone, :allow_concurrency, :schema_format, :verification_timeout, :lock_optimistically, :record_timestamps].each do |method|
866
+ :default_timezone, :allow_concurrency, :schema_format, :verification_timeout, :lock_optimistically, :record_timestamps].each do |method|
807
867
  assert Task.respond_to?(method)
808
868
  assert Task.respond_to?("#{method}=")
809
869
  assert Task.new.respond_to?(method)
810
870
  assert !Task.new.respond_to?("#{method}=")
811
871
  end
812
872
  end
813
-
873
+
814
874
  def test_customized_primary_key_remains_protected
815
875
  subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try')
816
876
  assert_nil subscriber.id
817
-
877
+
818
878
  keyboard = Keyboard.new(:key_number => 9, :name => 'nice try')
819
879
  assert_nil keyboard.id
820
880
  end
821
-
881
+
822
882
  def test_customized_primary_key_remains_protected_when_referred_to_as_id
823
883
  subscriber = Subscriber.new(:id => 'webster123', :name => 'nice try')
824
884
  assert_nil subscriber.id
825
-
885
+
826
886
  keyboard = Keyboard.new(:id => 9, :name => 'nice try')
827
887
  assert_nil keyboard.id
828
888
  end
@@ -837,34 +897,34 @@ class IBMDBBasicsTest < Test::Unit::TestCase
837
897
  def test_mass_assignment_accessible
838
898
  reply = Reply.new("title" => "hello", "content" => "world", "approved" => true)
839
899
  reply.save
840
-
900
+
841
901
  assert reply.approved?
842
902
 
843
903
  reply.approved = false
844
904
  reply.save
845
-
905
+
846
906
  assert !reply.approved?
847
907
  end
848
908
 
849
909
  def test_mass_assignment_protection_inheritance
850
910
  assert_nil LoosePerson.accessible_attributes
851
911
  assert_equal Set.new([ 'credit_rating', 'administrator' ]), LoosePerson.protected_attributes
852
-
912
+
853
913
  assert_nil LooseDescendant.accessible_attributes
854
914
  assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number' ]), LooseDescendant.protected_attributes
855
-
915
+
856
916
  assert_nil LooseDescendantSecond.accessible_attributes
857
917
  assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number', 'name' ]), LooseDescendantSecond.protected_attributes, 'Running attr_protected twice in one class should merge the protections'
858
-
918
+
859
919
  assert_nil TightPerson.protected_attributes
860
920
  assert_equal Set.new([ 'name', 'address' ]), TightPerson.accessible_attributes
861
-
921
+
862
922
  assert_nil TightDescendant.protected_attributes
863
923
  assert_equal Set.new([ 'name', 'address', 'phone_number' ]), TightDescendant.accessible_attributes
864
924
  end
865
925
 
866
926
  def test_readonly_attributes
867
- assert_equal Set.new([ 'title' ]), ReadonlyTitlePost.readonly_attributes
927
+ assert_equal Set.new([ 'title' , 'comments_count' ]), ReadonlyTitlePost.readonly_attributes
868
928
 
869
929
  post = ReadonlyTitlePost.create(:title => "cannot change this", :body => "changeable")
870
930
  post.reload
@@ -875,103 +935,181 @@ class IBMDBBasicsTest < Test::Unit::TestCase
875
935
  assert_equal "cannot change this", post.title
876
936
  assert_equal "changed", post.body
877
937
  end
878
-
938
+
879
939
  def test_multiparameter_attributes_on_date
880
940
  attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" }
881
941
  topic = Topic.find(1)
882
942
  topic.attributes = attributes
883
- # note that extra #to_date call allows test to pass for Oracle, which
943
+ # note that extra #to_date call allows test to pass for Oracle, which
884
944
  # treats dates/times the same
885
945
  assert_date_from_db Date.new(2004, 6, 24), topic.last_read.to_date
886
946
  end
887
-
947
+
888
948
  def test_multiparameter_attributes_on_date_with_empty_date
889
949
  attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "" }
890
950
  topic = Topic.find(1)
891
951
  topic.attributes = attributes
892
- # note that extra #to_date call allows test to pass for Oracle, which
952
+ # note that extra #to_date call allows test to pass for Oracle, which
893
953
  # treats dates/times the same
894
954
  assert_date_from_db Date.new(2004, 6, 1), topic.last_read.to_date
895
955
  end
896
-
956
+
897
957
  def test_multiparameter_attributes_on_date_with_all_empty
898
958
  attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "" }
899
959
  topic = Topic.find(1)
900
960
  topic.attributes = attributes
901
961
  assert_nil topic.last_read
902
962
  end
903
-
963
+
904
964
  def test_multiparameter_attributes_on_time
905
- attributes = {
906
- "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
965
+ attributes = {
966
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
907
967
  "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
908
968
  }
909
969
  topic = Topic.find(1)
910
970
  topic.attributes = attributes
911
971
  assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
912
972
  end
913
-
914
- def test_multiparameter_attributes_on_time_with_empty_seconds
915
- attributes = {
916
- "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
917
- "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => ""
973
+
974
+ def test_multiparameter_attributes_on_time_with_old_date
975
+ attributes = {
976
+ "written_on(1i)" => "1850", "written_on(2i)" => "6", "written_on(3i)" => "24",
977
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
918
978
  }
919
979
  topic = Topic.find(1)
920
980
  topic.attributes = attributes
921
- assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
922
- end
923
-
924
- def test_multiparameter_mass_assignment_protector
925
- task = Task.new
926
- time = Time.mktime(2000, 1, 1, 1)
927
- task.starting = time
928
- attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" }
929
- task.attributes = attributes
930
- assert_equal time, task.starting
981
+ # testing against to_s(:db) representation because either a Time or a DateTime might be returned, depending on platform
982
+ assert_equal "1850-06-24 16:24:00", topic.written_on.to_s(:db)
931
983
  end
932
984
 
933
- def test_multiparameter_assignment_of_aggregation
934
- customer = Customer.new
935
- address = Address.new("The Street", "The City", "The Country")
936
- attributes = { "address(1)" => address.street, "address(2)" => address.city, "address(3)" => address.country }
937
- customer.attributes = attributes
938
- assert_equal address, customer.address
985
+ def test_multiparameter_attributes_on_time_with_utc
986
+ ActiveRecord::Base.default_timezone = :utc
987
+ attributes = {
988
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
989
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
990
+ }
991
+ topic = Topic.find(1)
992
+ topic.attributes = attributes
993
+ assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on
994
+ ensure
995
+ ActiveRecord::Base.default_timezone = :local
939
996
  end
940
-
941
- def test_attributes_on_dummy_time
942
- # Oracle, SQL Server, and Sybase do not have a TIME datatype.
943
- return true if current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
944
-
997
+
998
+ def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes
999
+ ActiveRecord::Base.time_zone_aware_attributes = true
1000
+ ActiveRecord::Base.default_timezone = :utc
1001
+ Time.zone = TimeZone[-28800]
945
1002
  attributes = {
946
- "bonus_time" => "5:42:00AM"
1003
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
1004
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
947
1005
  }
948
1006
  topic = Topic.find(1)
949
1007
  topic.attributes = attributes
950
- assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
1008
+ assert_equal Time.utc(2004, 6, 24, 23, 24, 0), topic.written_on
1009
+ assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on.time
1010
+ assert_equal Time.zone, topic.written_on.time_zone
1011
+ ensure
1012
+ ActiveRecord::Base.time_zone_aware_attributes = false
1013
+ ActiveRecord::Base.default_timezone = :local
1014
+ Time.zone = nil
951
1015
  end
952
-
1016
+
1017
+ def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes_false
1018
+ ActiveRecord::Base.time_zone_aware_attributes = false
1019
+ Time.zone = TimeZone[-28800]
1020
+ attributes = {
1021
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
1022
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
1023
+ }
1024
+ topic = Topic.find(1)
1025
+ topic.attributes = attributes
1026
+ assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
1027
+ assert_equal false, topic.written_on.respond_to?(:time_zone)
1028
+ ensure
1029
+ Time.zone = nil
1030
+ end
1031
+
1032
+ def test_multiparameter_attributes_on_time_with_skip_time_zone_conversion_for_attributes
1033
+ ActiveRecord::Base.time_zone_aware_attributes = true
1034
+ ActiveRecord::Base.default_timezone = :utc
1035
+ Time.zone = TimeZone[-28800]
1036
+ Topic.skip_time_zone_conversion_for_attributes = [:written_on]
1037
+ attributes = {
1038
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
1039
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
1040
+ }
1041
+ topic = Topic.find(1)
1042
+ topic.attributes = attributes
1043
+ assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on
1044
+ assert_equal false, topic.written_on.respond_to?(:time_zone)
1045
+ ensure
1046
+ ActiveRecord::Base.time_zone_aware_attributes = false
1047
+ ActiveRecord::Base.default_timezone = :local
1048
+ Time.zone = nil
1049
+ Topic.skip_time_zone_conversion_for_attributes = []
1050
+ end
1051
+
1052
+ def test_multiparameter_attributes_on_time_with_empty_seconds
1053
+ attributes = {
1054
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
1055
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => ""
1056
+ }
1057
+ topic = Topic.find(1)
1058
+ topic.attributes = attributes
1059
+ assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
1060
+ end
1061
+
1062
+ def test_multiparameter_mass_assignment_protector
1063
+ task = Task.new
1064
+ time = Time.mktime(2000, 1, 1, 1)
1065
+ task.starting = time
1066
+ attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" }
1067
+ task.attributes = attributes
1068
+ assert_equal time, task.starting
1069
+ end
1070
+
1071
+ def test_multiparameter_assignment_of_aggregation
1072
+ customer = Customer.new
1073
+ address = Address.new("The Street", "The City", "The Country")
1074
+ attributes = { "address(1)" => address.street, "address(2)" => address.city, "address(3)" => address.country }
1075
+ customer.attributes = attributes
1076
+ assert_equal address, customer.address
1077
+ end
1078
+
1079
+ def test_attributes_on_dummy_time
1080
+ # Oracle, SQL Server, and Sybase do not have a TIME datatype.
1081
+ return true if current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
1082
+
1083
+ attributes = {
1084
+ "bonus_time" => "5:42:00AM"
1085
+ }
1086
+ topic = Topic.find(1)
1087
+ topic.attributes = attributes
1088
+ assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
1089
+ end
1090
+
953
1091
  def test_boolean
954
1092
  b_false = Booleantest.create({ "value" => false })
955
1093
  false_id = b_false.id
956
1094
  b_true = Booleantest.create({ "value" => true })
957
1095
  true_id = b_true.id
958
-
1096
+
959
1097
  b_false = Booleantest.find(false_id)
960
1098
  assert !b_false.value?
961
1099
  b_true = Booleantest.find(true_id)
962
1100
  assert b_true.value?
963
1101
  end
964
-
1102
+
965
1103
  def test_boolean_cast_from_string
966
1104
  b_false = Booleantest.create({ "value" => "0" })
967
1105
  false_id = b_false.id
968
1106
  b_true = Booleantest.create({ "value" => "1" })
969
1107
  true_id = b_true.id
970
-
1108
+
971
1109
  b_false = Booleantest.find(false_id)
972
1110
  assert !b_false.value?
973
1111
  b_true = Booleantest.find(true_id)
974
- assert b_true.value?
1112
+ assert b_true.value?
975
1113
  end
976
1114
 
977
1115
  def test_clone
@@ -980,54 +1118,54 @@ class IBMDBBasicsTest < Test::Unit::TestCase
980
1118
  assert_nothing_raised { cloned_topic = topic.clone }
981
1119
  assert_equal topic.title, cloned_topic.title
982
1120
  assert cloned_topic.new_record?
983
-
1121
+
984
1122
  # test if the attributes have been cloned
985
- topic.title = "a"
986
- cloned_topic.title = "b"
1123
+ topic.title = "a"
1124
+ cloned_topic.title = "b"
987
1125
  assert_equal "a", topic.title
988
1126
  assert_equal "b", cloned_topic.title
989
-
1127
+
990
1128
  # test if the attribute values have been cloned
991
1129
  topic.title = {"a" => "b"}
992
1130
  cloned_topic = topic.clone
993
- cloned_topic.title["a"] = "c"
1131
+ cloned_topic.title["a"] = "c"
994
1132
  assert_equal "b", topic.title["a"]
995
-
1133
+
996
1134
  #test if attributes set as part of after_initialize are cloned correctly
997
1135
  assert_equal topic.author_email_address, cloned_topic.author_email_address
998
-
1136
+
999
1137
  # test if saved clone object differs from original
1000
1138
  cloned_topic.save
1001
1139
  assert !cloned_topic.new_record?
1002
1140
  assert cloned_topic.id != topic.id
1003
1141
  end
1004
-
1142
+
1005
1143
  def test_clone_with_aggregate_of_same_name_as_attribute
1006
1144
  dev = DeveloperWithAggregate.find(1)
1007
1145
  assert_kind_of DeveloperSalary, dev.salary
1008
-
1146
+
1009
1147
  clone = nil
1010
1148
  assert_nothing_raised { clone = dev.clone }
1011
1149
  assert_kind_of DeveloperSalary, clone.salary
1012
1150
  assert_equal dev.salary.amount, clone.salary.amount
1013
1151
  assert clone.new_record?
1014
-
1152
+
1015
1153
  # test if the attributes have been cloned
1016
1154
  original_amount = clone.salary.amount
1017
1155
  dev.salary.amount = 1
1018
1156
  assert_equal original_amount, clone.salary.amount
1019
-
1157
+
1020
1158
  assert clone.save
1021
1159
  assert !clone.new_record?
1022
1160
  assert clone.id != dev.id
1023
1161
  end
1024
-
1162
+
1025
1163
  def test_clone_preserves_subtype
1026
1164
  clone = nil
1027
1165
  assert_nothing_raised { clone = Company.find(3).clone }
1028
1166
  assert_kind_of Client, clone
1029
1167
  end
1030
-
1168
+
1031
1169
  def test_bignum
1032
1170
  company = Company.find(1)
1033
1171
  company.rating = 2147483647
@@ -1035,69 +1173,69 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1035
1173
  company = Company.find(1)
1036
1174
  assert_equal 2147483647, company.rating
1037
1175
  end
1038
-
1176
+
1039
1177
  # TODO: extend defaults tests to other databases!
1040
1178
  if current_adapter?(:PostgreSQLAdapter)
1041
1179
  def test_default
1042
1180
  default = Default.new
1043
-
1181
+
1044
1182
  # fixed dates / times
1045
1183
  assert_equal Date.new(2004, 1, 1), default.fixed_date
1046
1184
  assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time
1047
-
1185
+
1048
1186
  # char types
1049
1187
  assert_equal 'Y', default.char1
1050
1188
  assert_equal 'a varchar field', default.char2
1051
1189
  assert_equal 'a text field', default.char3
1052
1190
  end
1053
-
1191
+
1054
1192
  class Geometric < ActiveRecord::Base; end
1055
1193
  def test_geometric_content
1056
-
1194
+
1057
1195
  # accepted format notes:
1058
1196
  # ()'s aren't required
1059
1197
  # values can be a mix of float or integer
1060
-
1198
+
1061
1199
  g = Geometric.new(
1062
- :a_point => '(5.0, 6.1)',
1063
- #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
1064
- :a_line_segment => '(2.0, 3), (5.5, 7.0)',
1065
- :a_box => '2.0, 3, 5.5, 7.0',
1066
- :a_path => '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]', # [ ] is an open path
1067
- :a_polygon => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))',
1068
- :a_circle => '<(5.3, 10.4), 2>'
1200
+ :a_point => '(5.0, 6.1)',
1201
+ #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
1202
+ :a_line_segment => '(2.0, 3), (5.5, 7.0)',
1203
+ :a_box => '2.0, 3, 5.5, 7.0',
1204
+ :a_path => '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]', # [ ] is an open path
1205
+ :a_polygon => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))',
1206
+ :a_circle => '<(5.3, 10.4), 2>'
1069
1207
  )
1070
-
1208
+
1071
1209
  assert g.save
1072
-
1210
+
1073
1211
  # Reload and check that we have all the geometric attributes.
1074
1212
  h = Geometric.find(g.id)
1075
-
1213
+
1076
1214
  assert_equal '(5,6.1)', h.a_point
1077
1215
  assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
1078
1216
  assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner
1079
1217
  assert_equal '[(2,3),(5.5,7),(8.5,11)]', h.a_path
1080
1218
  assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
1081
1219
  assert_equal '<(5.3,10.4),2>', h.a_circle
1082
-
1220
+
1083
1221
  # use a geometric function to test for an open path
1084
1222
  objs = Geometric.find_by_sql ["select isopen(a_path) from geometrics where id = ?", g.id]
1085
1223
  assert_equal objs[0].isopen, 't'
1086
-
1224
+
1087
1225
  # test alternate formats when defining the geometric types
1088
1226
 
1089
1227
  g = Geometric.new(
1090
- :a_point => '5.0, 6.1',
1091
- #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
1092
- :a_line_segment => '((2.0, 3), (5.5, 7.0))',
1093
- :a_box => '(2.0, 3), (5.5, 7.0)',
1094
- :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path
1095
- :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0',
1096
- :a_circle => '((5.3, 10.4), 2)'
1228
+ :a_point => '5.0, 6.1',
1229
+ #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
1230
+ :a_line_segment => '((2.0, 3), (5.5, 7.0))',
1231
+ :a_box => '(2.0, 3), (5.5, 7.0)',
1232
+ :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path
1233
+ :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0',
1234
+ :a_circle => '((5.3, 10.4), 2)'
1097
1235
  )
1098
-
1236
+
1099
1237
  assert g.save
1100
-
1238
+
1101
1239
  # Reload and check that we have all the geometric attributes.
1102
1240
  h = Geometric.find(g.id)
1103
1241
 
@@ -1107,63 +1245,62 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1107
1245
  assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path
1108
1246
  assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
1109
1247
  assert_equal '<(5.3,10.4),2>', h.a_circle
1110
-
1248
+
1111
1249
  # use a geometric function to test for an closed path
1112
1250
  objs = Geometric.find_by_sql ["select isclosed(a_path) from geometrics where id = ?", g.id]
1113
1251
  assert_equal objs[0].isclosed, 't'
1114
1252
  end
1115
1253
  end
1116
-
1254
+
1117
1255
  class NumericData < ActiveRecord::Base
1118
1256
  self.table_name = 'numeric_data'
1119
1257
  end
1120
-
1258
+
1121
1259
  def test_numeric_fields
1122
1260
  m = NumericData.new(
1123
- :bank_balance => 1586.43,
1124
- :big_bank_balance => BigDecimal("1000234000567.95"),
1125
- :world_population => 6000000000,
1126
- :my_house_population => 3
1261
+ :bank_balance => 1586.43,
1262
+ :big_bank_balance => BigDecimal("1000234000567.95"),
1263
+ :world_population => 6000000000,
1264
+ :my_house_population => 3
1127
1265
  )
1128
1266
  assert m.save
1129
-
1267
+
1130
1268
  m1 = NumericData.find(m.id)
1131
1269
  assert_not_nil m1
1132
-
1270
+
1133
1271
  # As with migration_test.rb, we should make world_population >= 2**62
1134
1272
  # to cover 64-bit platforms and test it is a Bignum, but the main thing
1135
1273
  # is that it's an Integer.
1136
- unless current_adapter?(:IBM_DBAdapter)
1137
- assert_kind_of Integer, m1.world_population
1138
- else
1139
- assert_kind_of BigDecimal, m1.world_population
1140
- end
1274
+ unless current_adapter?(:IBM_DBAdapter)
1275
+ assert_kind_of Integer, m1.world_population
1276
+ else
1277
+ assert_kind_of BigDecimal, m1.world_population
1278
+ end
1141
1279
  assert_equal 6000000000, m1.world_population
1142
-
1143
- unless current_adapter?(:IBM_DBAdapter)
1144
- assert_kind_of Fixnum, m1.my_house_population
1145
- else
1146
- assert_kind_of BigDecimal, m1.my_house_population
1147
- end
1280
+ unless current_adapter?(:IBM_DBAdapter)
1281
+ assert_kind_of Fixnum, m1.my_house_population
1282
+ else
1283
+ assert_kind_of BigDecimal, m1.my_house_population
1284
+ end
1148
1285
  assert_equal 3, m1.my_house_population
1149
-
1286
+
1150
1287
  assert_kind_of BigDecimal, m1.bank_balance
1151
1288
  assert_equal BigDecimal("1586.43"), m1.bank_balance
1152
-
1289
+
1153
1290
  assert_kind_of BigDecimal, m1.big_bank_balance
1154
1291
  assert_equal BigDecimal("1000234000567.95"), m1.big_bank_balance
1155
1292
  end
1156
-
1293
+
1157
1294
  def test_auto_id
1158
1295
  auto = AutoId.new
1159
1296
  auto.save
1160
1297
  assert (auto.id > 0)
1161
1298
  end
1162
-
1299
+
1163
1300
  def quote_column_name(name)
1164
1301
  "<#{name}>"
1165
1302
  end
1166
-
1303
+
1167
1304
  def test_quote_keys
1168
1305
  ar = AutoId.new
1169
1306
  source = {"foo" => "bar", "baz" => "quux"}
@@ -1172,13 +1309,13 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1172
1309
  assert_equal("<foo>", inverted["bar"])
1173
1310
  assert_equal("<baz>", inverted["quux"])
1174
1311
  end
1175
-
1312
+
1176
1313
  def test_sql_injection_via_find
1177
1314
  assert_raises(ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid) do
1178
1315
  Topic.find("123456 OR id > 0")
1179
1316
  end
1180
1317
  end
1181
-
1318
+
1182
1319
  def test_column_name_properly_quoted
1183
1320
  col_record = ColumnName.new
1184
1321
  col_record.references = 40
@@ -1188,30 +1325,30 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1188
1325
  assert_not_nil c2 = ColumnName.find(col_record.id)
1189
1326
  assert_equal(41, c2.references)
1190
1327
  end
1191
-
1328
+
1192
1329
  def test_quoting_arrays
1193
1330
  replies = Reply.find(:all, :conditions => [ "id IN (?)", topics(:first).replies.collect(&:id) ])
1194
1331
  assert_equal topics(:first).replies.size, replies.size
1195
-
1332
+
1196
1333
  replies = Reply.find(:all, :conditions => [ "id IN (?)", [] ])
1197
1334
  assert_equal 0, replies.size
1198
1335
  end
1199
-
1336
+
1200
1337
  MyObject = Struct.new :attribute1, :attribute2
1201
1338
 
1202
1339
  def test_serialized_attribute
1203
1340
  myobj = MyObject.new('value1', 'value2')
1204
- topic = Topic.create("content" => myobj)
1341
+ topic = Topic.create("content" => myobj)
1205
1342
  Topic.serialize("content", MyObject)
1206
1343
  assert_equal(myobj, topic.content)
1207
1344
  end
1208
-
1345
+
1209
1346
  def test_nil_serialized_attribute_with_class_constraint
1210
1347
  myobj = MyObject.new('value1', 'value2')
1211
1348
  topic = Topic.new
1212
1349
  assert_nil topic.content
1213
1350
  end
1214
-
1351
+
1215
1352
  def test_should_raise_exception_on_serialized_attribute_with_type_mismatch
1216
1353
  myobj = MyObject.new('value1', 'value2')
1217
1354
  topic = Topic.new(:content => myobj)
@@ -1221,7 +1358,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1221
1358
  ensure
1222
1359
  Topic.serialize(:content)
1223
1360
  end
1224
-
1361
+
1225
1362
  def test_serialized_attribute_with_class_constraint
1226
1363
  settings = { "color" => "blue" }
1227
1364
  Topic.serialize(:content, Hash)
@@ -1231,48 +1368,50 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1231
1368
  ensure
1232
1369
  Topic.serialize(:content)
1233
1370
  end
1234
-
1371
+
1235
1372
  def test_quote
1236
1373
  author_name = "\\ \001 ' \n \\n \""
1237
1374
  topic = Topic.create('author_name' => author_name)
1238
1375
  assert_equal author_name, Topic.find(topic.id).author_name
1239
1376
  end
1240
1377
 
1241
- def test_quote_chars
1242
- str = 'The Narrator'
1243
- topic = Topic.create(:author_name => str)
1244
- assert_equal str, topic.author_name
1245
-
1246
- assert_kind_of ActiveSupport::Multibyte::Chars, str.chars
1247
- topic = Topic.find_by_author_name(str.chars)
1248
-
1249
- assert_kind_of Topic, topic
1250
- assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars"
1378
+ if RUBY_VERSION < '1.9'
1379
+ def test_quote_chars
1380
+ str = 'The Narrator'
1381
+ topic = Topic.create(:author_name => str)
1382
+ assert_equal str, topic.author_name
1383
+
1384
+ assert_kind_of ActiveSupport::Multibyte::Chars, str.chars
1385
+ topic = Topic.find_by_author_name(str.chars)
1386
+
1387
+ assert_kind_of Topic, topic
1388
+ assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars"
1389
+ end
1251
1390
  end
1252
1391
 
1253
1392
  def test_class_level_destroy
1254
1393
  should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
1255
1394
  Topic.find(1).replies << should_be_destroyed_reply
1256
-
1395
+
1257
1396
  Topic.destroy(1)
1258
1397
  assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
1259
1398
  assert_raise(ActiveRecord::RecordNotFound) { Reply.find(should_be_destroyed_reply.id) }
1260
1399
  end
1261
-
1400
+
1262
1401
  def test_class_level_delete
1263
1402
  should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
1264
1403
  Topic.find(1).replies << should_be_destroyed_reply
1265
-
1404
+
1266
1405
  Topic.delete(1)
1267
1406
  assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
1268
1407
  assert_nothing_raised { Reply.find(should_be_destroyed_reply.id) }
1269
1408
  end
1270
-
1409
+
1271
1410
  def test_increment_attribute
1272
1411
  assert_equal 50, accounts(:signals37).credit_limit
1273
1412
  accounts(:signals37).increment! :credit_limit
1274
- assert_equal 51, accounts(:signals37, :reload).credit_limit
1275
-
1413
+ assert_equal 51, accounts(:signals37, :reload).credit_limit
1414
+
1276
1415
  accounts(:signals37).increment(:credit_limit).increment!(:credit_limit)
1277
1416
  assert_equal 53, accounts(:signals37, :reload).credit_limit
1278
1417
  end
@@ -1283,16 +1422,34 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1283
1422
  assert_equal 1, topics(:first).parent_id
1284
1423
  end
1285
1424
 
1425
+ def test_increment_attribute_by
1426
+ assert_equal 50, accounts(:signals37).credit_limit
1427
+ accounts(:signals37).increment! :credit_limit, 5
1428
+ assert_equal 55, accounts(:signals37, :reload).credit_limit
1429
+
1430
+ accounts(:signals37).increment(:credit_limit, 1).increment!(:credit_limit, 3)
1431
+ assert_equal 59, accounts(:signals37, :reload).credit_limit
1432
+ end
1433
+
1286
1434
  def test_decrement_attribute
1287
1435
  assert_equal 50, accounts(:signals37).credit_limit
1288
-
1436
+
1289
1437
  accounts(:signals37).decrement!(:credit_limit)
1290
1438
  assert_equal 49, accounts(:signals37, :reload).credit_limit
1291
-
1439
+
1292
1440
  accounts(:signals37).decrement(:credit_limit).decrement!(:credit_limit)
1293
1441
  assert_equal 47, accounts(:signals37, :reload).credit_limit
1294
1442
  end
1295
1443
 
1444
+ def test_decrement_attribute_by
1445
+ assert_equal 50, accounts(:signals37).credit_limit
1446
+ accounts(:signals37).decrement! :credit_limit, 5
1447
+ assert_equal 45, accounts(:signals37, :reload).credit_limit
1448
+
1449
+ accounts(:signals37).decrement(:credit_limit, 1).decrement!(:credit_limit, 3)
1450
+ assert_equal 41, accounts(:signals37, :reload).credit_limit
1451
+ end
1452
+
1296
1453
  def test_toggle_attribute
1297
1454
  assert !topics(:first).approved?
1298
1455
  topics(:first).toggle!(:approved)
@@ -1303,7 +1460,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1303
1460
  topic.reload
1304
1461
  assert topic.approved?
1305
1462
  end
1306
-
1463
+
1307
1464
  def test_reload
1308
1465
  t1 = Topic.find(1)
1309
1466
  t2 = Topic.find(1)
@@ -1312,19 +1469,19 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1312
1469
  t2.reload
1313
1470
  assert_equal t1.title, t2.title
1314
1471
  end
1315
-
1472
+
1316
1473
  def test_define_attr_method_with_value
1317
1474
  k = Class.new( ActiveRecord::Base )
1318
1475
  k.send(:define_attr_method, :table_name, "foo")
1319
1476
  assert_equal "foo", k.table_name
1320
1477
  end
1321
-
1478
+
1322
1479
  def test_define_attr_method_with_block
1323
1480
  k = Class.new( ActiveRecord::Base )
1324
1481
  k.send(:define_attr_method, :primary_key) { "sys_" + original_primary_key }
1325
1482
  assert_equal "sys_id", k.primary_key
1326
1483
  end
1327
-
1484
+
1328
1485
  def test_set_table_name_with_value
1329
1486
  k = Class.new( ActiveRecord::Base )
1330
1487
  k.table_name = "foo"
@@ -1332,13 +1489,13 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1332
1489
  k.set_table_name "bar"
1333
1490
  assert_equal "bar", k.table_name
1334
1491
  end
1335
-
1492
+
1336
1493
  def test_set_table_name_with_block
1337
1494
  k = Class.new( ActiveRecord::Base )
1338
1495
  k.set_table_name { "ks" }
1339
1496
  assert_equal "ks", k.table_name
1340
1497
  end
1341
-
1498
+
1342
1499
  def test_set_primary_key_with_value
1343
1500
  k = Class.new( ActiveRecord::Base )
1344
1501
  k.primary_key = "foo"
@@ -1346,13 +1503,13 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1346
1503
  k.set_primary_key "bar"
1347
1504
  assert_equal "bar", k.primary_key
1348
1505
  end
1349
-
1506
+
1350
1507
  def test_set_primary_key_with_block
1351
1508
  k = Class.new( ActiveRecord::Base )
1352
1509
  k.set_primary_key { "sys_" + original_primary_key }
1353
1510
  assert_equal "sys_id", k.primary_key
1354
1511
  end
1355
-
1512
+
1356
1513
  def test_set_inheritance_column_with_value
1357
1514
  k = Class.new( ActiveRecord::Base )
1358
1515
  k.inheritance_column = "foo"
@@ -1360,13 +1517,13 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1360
1517
  k.set_inheritance_column "bar"
1361
1518
  assert_equal "bar", k.inheritance_column
1362
1519
  end
1363
-
1520
+
1364
1521
  def test_set_inheritance_column_with_block
1365
1522
  k = Class.new( ActiveRecord::Base )
1366
1523
  k.set_inheritance_column { original_inheritance_column + "_id" }
1367
1524
  assert_equal "type_id", k.inheritance_column
1368
1525
  end
1369
-
1526
+
1370
1527
  def test_count_with_join
1371
1528
  res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'"
1372
1529
 
@@ -1376,7 +1533,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1376
1533
  res3 = nil
1377
1534
  assert_nothing_raised do
1378
1535
  res3 = Post.count(:conditions => "posts.#{QUOTED_TYPE} = 'Post'",
1379
- :joins => "LEFT JOIN comments ON posts.id=comments.post_id")
1536
+ :joins => "LEFT JOIN comments ON posts.id=comments.post_id")
1380
1537
  end
1381
1538
  assert_equal res, res3
1382
1539
 
@@ -1384,53 +1541,53 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1384
1541
  res5 = nil
1385
1542
  assert_nothing_raised do
1386
1543
  res5 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
1387
- :joins => "p, comments co",
1388
- :select => "p.id")
1544
+ :joins => "p, comments co",
1545
+ :select => "p.id")
1389
1546
  end
1390
-
1391
- assert_equal res4, res5
1392
-
1547
+
1548
+ assert_equal res4, res5
1549
+
1393
1550
  unless current_adapter?(:SQLite2Adapter, :DeprecatedSQLiteAdapter)
1394
1551
  res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
1395
1552
  res7 = nil
1396
1553
  assert_nothing_raised do
1397
1554
  res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
1398
- :joins => "p, comments co",
1399
- :select => "p.id",
1400
- :distinct => true)
1555
+ :joins => "p, comments co",
1556
+ :select => "p.id",
1557
+ :distinct => true)
1401
1558
  end
1402
1559
  assert_equal res6, res7
1403
1560
  end
1404
1561
  end
1405
1562
 
1406
- def test_clear_association_cache_stored
1563
+ def test_clear_association_cache_stored
1407
1564
  firm = Firm.find(1)
1408
1565
  assert_kind_of Firm, firm
1409
-
1566
+
1410
1567
  firm.clear_association_cache
1411
1568
  assert_equal Firm.find(1).clients.collect{ |x| x.name }.sort, firm.clients.collect{ |x| x.name }.sort
1412
1569
  end
1413
1570
 
1414
1571
  def test_clear_association_cache_new_record
1415
- firm = Firm.new
1416
- client_stored = Client.find(3)
1417
- client_new = Client.new
1418
- client_new.name = "The Joneses"
1419
- clients = [ client_stored, client_new ]
1420
-
1421
- firm.clients << clients
1422
- assert_equal clients.map(&:name).to_set, firm.clients.map(&:name).to_set
1423
-
1424
- firm.clear_association_cache
1425
- assert_equal clients.map(&:name).to_set, firm.clients.map(&:name).to_set
1572
+ firm = Firm.new
1573
+ client_stored = Client.find(3)
1574
+ client_new = Client.new
1575
+ client_new.name = "The Joneses"
1576
+ clients = [ client_stored, client_new ]
1577
+
1578
+ firm.clients << clients
1579
+ assert_equal clients.map(&:name).to_set, firm.clients.map(&:name).to_set
1580
+
1581
+ firm.clear_association_cache
1582
+ assert_equal clients.map(&:name).to_set, firm.clients.map(&:name).to_set
1426
1583
  end
1427
-
1584
+
1428
1585
  def test_interpolate_sql
1429
1586
  assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo@bar') }
1430
1587
  assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar) baz') }
1431
1588
  assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar} baz') }
1432
1589
  end
1433
-
1590
+
1434
1591
  def test_scoped_find_conditions
1435
1592
  scoped_developers = Developer.with_scope(:find => { :conditions => 'salary > 90000' }) do
1436
1593
  Developer.find(:all, :conditions => 'id < 5')
@@ -1442,7 +1599,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1442
1599
  def test_scoped_find_limit_offset
1443
1600
  scoped_developers = Developer.with_scope(:find => { :limit => 3, :offset => 2 }) do
1444
1601
  Developer.find(:all, :order => 'id')
1445
- end
1602
+ end
1446
1603
  assert !scoped_developers.include?(developers(:david))
1447
1604
  assert !scoped_developers.include?(developers(:jamis))
1448
1605
  assert_equal 3, scoped_developers.size
@@ -1451,18 +1608,18 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1451
1608
  developers = Developer.find(:all, :order => 'id')
1452
1609
  assert_equal Developer.count, developers.size
1453
1610
  end
1454
-
1455
- def test_scoped_find_order
1456
- # Test order in scope
1611
+
1612
+ def test_scoped_find_order
1613
+ # Test order in scope
1457
1614
  scoped_developers = Developer.with_scope(:find => { :limit => 1, :order => 'salary DESC' }) do
1458
1615
  Developer.find(:all)
1459
- end
1616
+ end
1460
1617
  assert_equal 'Jamis', scoped_developers.first.name
1461
1618
  assert scoped_developers.include?(developers(:jamis))
1462
1619
  # Test scope without order and order in find
1463
1620
  scoped_developers = Developer.with_scope(:find => { :limit => 1 }) do
1464
1621
  Developer.find(:all, :order => 'salary DESC')
1465
- end
1622
+ end
1466
1623
  # Test scope order + find order, find has priority
1467
1624
  scoped_developers = Developer.with_scope(:find => { :limit => 3, :order => 'id DESC' }) do
1468
1625
  Developer.find(:all, :order => 'salary ASC')
@@ -1474,7 +1631,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1474
1631
  developers = Developer.find(:all, :order => 'id', :limit => 1)
1475
1632
  assert scoped_developers.include?(developers(:david))
1476
1633
  end
1477
-
1634
+
1478
1635
  def test_scoped_find_limit_offset_including_has_many_association
1479
1636
  topics = Topic.with_scope(:find => {:limit => 1, :offset => 1, :include => :replies}) do
1480
1637
  Topic.find(:all, :order => "topics.id")
@@ -1482,7 +1639,7 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1482
1639
  assert_equal 1, topics.size
1483
1640
  assert_equal 2, topics.first.id
1484
1641
  end
1485
-
1642
+
1486
1643
  def test_scoped_find_order_including_has_many_association
1487
1644
  developers = Developer.with_scope(:find => { :order => 'developers.salary DESC', :include => :projects }) do
1488
1645
  Developer.find(:all)
@@ -1492,105 +1649,136 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1492
1649
  assert developers[i-1].salary >= developers[i].salary
1493
1650
  end
1494
1651
  end
1495
-
1652
+
1653
+ def test_find_last
1654
+ last = Developer.find :last
1655
+ assert_equal last, Developer.find(:first, :order => 'id desc')
1656
+ end
1657
+
1658
+ def test_last
1659
+ assert_equal Developer.find(:first, :order => 'id desc'), Developer.last
1660
+ end
1661
+
1662
+ def test_all_with_conditions
1663
+ assert_equal Developer.find(:all, :order => 'id desc'), Developer.all(:order => 'id desc')
1664
+ end
1665
+
1666
+ def test_find_ordered_last
1667
+ last = Developer.find :last, :order => 'developers.salary ASC'
1668
+ assert_equal last, Developer.find(:all, :order => 'developers.salary ASC').last
1669
+ end
1670
+
1671
+ def test_find_reverse_ordered_last
1672
+ last = Developer.find :last, :order => 'developers.salary DESC'
1673
+ assert_equal last, Developer.find(:all, :order => 'developers.salary DESC').last
1674
+ end
1675
+
1676
+ def test_find_multiple_ordered_last
1677
+ last = Developer.find :last, :order => 'developers.name, developers.salary DESC'
1678
+ assert_equal last, Developer.find(:all, :order => 'developers.name, developers.salary DESC').last
1679
+ end
1680
+
1681
+ def test_find_scoped_ordered_last
1682
+ last_developer = Developer.with_scope(:find => { :order => 'developers.salary ASC' }) do
1683
+ Developer.find(:last)
1684
+ end
1685
+ assert_equal last_developer, Developer.find(:all, :order => 'developers.salary ASC').last
1686
+ end
1687
+
1496
1688
  def test_abstract_class
1497
1689
  assert !ActiveRecord::Base.abstract_class?
1498
1690
  assert LoosePerson.abstract_class?
1499
1691
  assert !LooseDescendant.abstract_class?
1500
1692
  end
1501
-
1693
+
1502
1694
  def test_base_class
1503
1695
  assert_equal LoosePerson, LoosePerson.base_class
1504
1696
  assert_equal LooseDescendant, LooseDescendant.base_class
1505
1697
  assert_equal TightPerson, TightPerson.base_class
1506
1698
  assert_equal TightPerson, TightDescendant.base_class
1507
-
1699
+
1508
1700
  assert_equal Post, Post.base_class
1509
1701
  assert_equal Post, SpecialPost.base_class
1510
1702
  assert_equal Post, StiPost.base_class
1511
1703
  assert_equal SubStiPost, SubStiPost.base_class
1512
1704
  end
1513
-
1705
+
1514
1706
  def test_descends_from_active_record
1515
1707
  # Tries to call Object.abstract_class?
1516
1708
  assert_raise(NoMethodError) do
1517
1709
  ActiveRecord::Base.descends_from_active_record?
1518
1710
  end
1519
-
1711
+
1520
1712
  # Abstract subclass of AR::Base.
1521
1713
  assert LoosePerson.descends_from_active_record?
1522
-
1714
+
1523
1715
  # Concrete subclass of an abstract class.
1524
1716
  assert LooseDescendant.descends_from_active_record?
1525
-
1717
+
1526
1718
  # Concrete subclass of AR::Base.
1527
1719
  assert TightPerson.descends_from_active_record?
1528
-
1720
+
1529
1721
  # Concrete subclass of a concrete class but has no type column.
1530
1722
  assert TightDescendant.descends_from_active_record?
1531
-
1723
+
1532
1724
  # Concrete subclass of AR::Base.
1533
1725
  assert Post.descends_from_active_record?
1534
-
1726
+
1535
1727
  # Abstract subclass of a concrete class which has a type column.
1536
1728
  # This is pathological, as you'll never have Sub < Abstract < Concrete.
1537
1729
  assert !StiPost.descends_from_active_record?
1538
-
1730
+
1539
1731
  # Concrete subclasses an abstract class which has a type column.
1540
1732
  assert !SubStiPost.descends_from_active_record?
1541
1733
  end
1542
-
1734
+
1543
1735
  def test_find_on_abstract_base_class_doesnt_use_type_condition
1544
1736
  old_class = LooseDescendant
1545
1737
  Object.send :remove_const, :LooseDescendant
1546
-
1547
- descendant = old_class.create!
1738
+
1739
+ descendant = old_class.create! :first_name => 'bob'
1548
1740
  assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}"
1549
1741
  ensure
1550
1742
  unless Object.const_defined?(:LooseDescendant)
1551
1743
  Object.const_set :LooseDescendant, old_class
1552
1744
  end
1553
1745
  end
1554
-
1746
+
1555
1747
  def test_assert_queries
1556
1748
  query = lambda { ActiveRecord::Base.connection.execute 'select count(*) from developers' }
1557
1749
  assert_queries(2) { 2.times { query.call } }
1558
1750
  assert_queries 1, &query
1559
1751
  assert_no_queries { assert true }
1560
1752
  end
1561
-
1753
+
1562
1754
  def test_to_xml
1563
1755
  xml = REXML::Document.new(topics(:first).to_xml(:indent => 0))
1564
1756
  bonus_time_in_current_timezone = topics(:first).bonus_time.xmlschema
1565
1757
  written_on_in_current_timezone = topics(:first).written_on.xmlschema
1566
1758
  last_read_in_current_timezone = topics(:first).last_read.xmlschema
1567
-
1759
+
1568
1760
  assert_equal "topic", xml.root.name
1569
1761
  assert_equal "The First Topic" , xml.elements["//title"].text
1570
1762
  assert_equal "David" , xml.elements["//author-name"].text
1571
-
1763
+
1572
1764
  assert_equal "1", xml.elements["//id"].text
1573
- unless ActiveRecord::Base.connection.servertype.class.name.include?('::IBM_IDS')
1574
1765
  assert_equal "integer" , xml.elements["//id"].attributes['type']
1575
- else
1576
- assert_equal "serial" , xml.elements["//id"].attributes['type']
1577
- end
1578
-
1766
+
1579
1767
  assert_equal "1", xml.elements["//replies-count"].text
1580
1768
  assert_equal "integer" , xml.elements["//replies-count"].attributes['type']
1581
-
1769
+
1582
1770
  assert_equal written_on_in_current_timezone, xml.elements["//written-on"].text
1583
1771
  assert_equal "datetime" , xml.elements["//written-on"].attributes['type']
1584
-
1772
+
1585
1773
  assert_equal "--- Have a nice day\n" , xml.elements["//content"].text
1586
1774
  assert_equal "yaml" , xml.elements["//content"].attributes['type']
1587
-
1775
+
1588
1776
  assert_equal "david@loudthinking.com", xml.elements["//author-email-address"].text
1589
-
1777
+
1590
1778
  assert_equal nil, xml.elements["//parent-id"].text
1591
1779
  assert_equal "integer", xml.elements["//parent-id"].attributes['type']
1592
1780
  assert_equal "true", xml.elements["//parent-id"].attributes['nil']
1593
-
1781
+
1594
1782
  if current_adapter?(:SybaseAdapter, :SQLServerAdapter, :OracleAdapter)
1595
1783
  assert_equal last_read_in_current_timezone, xml.elements["//last-read"].text
1596
1784
  assert_equal "datetime" , xml.elements["//last-read"].attributes['type']
@@ -1598,40 +1786,40 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1598
1786
  assert_equal "2004-04-15", xml.elements["//last-read"].text
1599
1787
  assert_equal "date" , xml.elements["//last-read"].attributes['type']
1600
1788
  end
1601
-
1789
+
1602
1790
  # Oracle and DB2 don't have true boolean or time-only fields
1603
1791
  unless current_adapter?(:OracleAdapter, :DB2Adapter)
1604
1792
  assert_equal "false", xml.elements["//approved"].text
1605
1793
  assert_equal "boolean" , xml.elements["//approved"].attributes['type']
1606
-
1794
+
1607
1795
  assert_equal bonus_time_in_current_timezone, xml.elements["//bonus-time"].text
1608
1796
  assert_equal "datetime" , xml.elements["//bonus-time"].attributes['type']
1609
1797
  end
1610
1798
  end
1611
-
1799
+
1612
1800
  def test_to_xml_skipping_attributes
1613
1801
  xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [:title, :replies_count])
1614
1802
  assert_equal "<topic>", xml.first(7)
1615
1803
  assert !xml.include?(%(<title>The First Topic</title>))
1616
- assert xml.include?(%(<author-name>David</author-name>))
1617
-
1804
+ assert xml.include?(%(<author-name>David</author-name>))
1805
+
1618
1806
  xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [:title, :author_name, :replies_count])
1619
1807
  assert !xml.include?(%(<title>The First Topic</title>))
1620
- assert !xml.include?(%(<author-name>David</author-name>))
1808
+ assert !xml.include?(%(<author-name>David</author-name>))
1621
1809
  end
1622
-
1810
+
1623
1811
  def test_to_xml_including_has_many_association
1624
1812
  xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :include => :replies, :except => :replies_count)
1625
1813
  assert_equal "<topic>", xml.first(7)
1626
1814
  assert xml.include?(%(<replies type="array"><reply>))
1627
- assert xml.include?(%(<title>The Second Topic's of the day</title>))
1815
+ assert xml.include?(%(<title>The Second Topic of the day</title>))
1628
1816
  end
1629
-
1817
+
1630
1818
  def test_array_to_xml_including_has_many_association
1631
1819
  xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :include => :replies)
1632
1820
  assert xml.include?(%(<replies type="array"><reply>))
1633
1821
  end
1634
-
1822
+
1635
1823
  def test_array_to_xml_including_methods
1636
1824
  xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :methods => [ :topic_id ])
1637
1825
  assert xml.include?(%(<topic-id type="integer">#{topics(:first).topic_id}</topic-id>)), xml
@@ -1643,18 +1831,18 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1643
1831
  assert xml.include?(companies(:first_firm).account.to_xml(:indent => 0, :skip_instruct => true))
1644
1832
  assert xml.include?(companies(:rails_core).account.to_xml(:indent => 0, :skip_instruct => true))
1645
1833
  end
1646
-
1834
+
1647
1835
  def test_array_to_xml_including_belongs_to_association
1648
1836
  xml = [ companies(:first_client), companies(:second_client), companies(:another_client) ].to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
1649
1837
  assert xml.include?(companies(:first_client).to_xml(:indent => 0, :skip_instruct => true))
1650
1838
  assert xml.include?(companies(:second_client).firm.to_xml(:indent => 0, :skip_instruct => true))
1651
1839
  assert xml.include?(companies(:another_client).firm.to_xml(:indent => 0, :skip_instruct => true))
1652
1840
  end
1653
-
1841
+
1654
1842
  def test_to_xml_including_belongs_to_association
1655
1843
  xml = companies(:first_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
1656
1844
  assert !xml.include?("<firm>")
1657
-
1845
+
1658
1846
  xml = companies(:second_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
1659
1847
  assert xml.include?("<firm>")
1660
1848
  end
@@ -1665,11 +1853,11 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1665
1853
  assert xml.include?(%(<account>))
1666
1854
  assert xml.include?(%(<clients type="array"><client>))
1667
1855
  end
1668
-
1856
+
1669
1857
  def test_to_xml_including_multiple_associations_with_options
1670
1858
  xml = companies(:first_firm).to_xml(
1671
- :indent => 0, :skip_instruct => true,
1672
- :include => { :clients => { :only => :name } }
1859
+ :indent => 0, :skip_instruct => true,
1860
+ :include => { :clients => { :only => :name } }
1673
1861
  )
1674
1862
 
1675
1863
  assert_equal "<firm>", xml.first(6)
@@ -1692,23 +1880,6 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1692
1880
  assert xml.include?(%(<arbitrary-element>#{value}</arbitrary-element>))
1693
1881
  end
1694
1882
 
1695
- def test_except_attributes
1696
- assert_equal(
1697
- %w( author_name type id approved replies_count bonus_time written_on content author_email_address parent_id last_read),
1698
- topics(:first).attributes(:except => :title).keys
1699
- )
1700
-
1701
- assert_equal(
1702
- %w( replies_count bonus_time written_on content author_email_address parent_id last_read),
1703
- topics(:first).attributes(:except => [ :title, :id, :type, :approved, :author_name ]).keys
1704
- )
1705
- end
1706
-
1707
- def test_include_attributes
1708
- assert_equal(%w( title ), topics(:first).attributes(:only => :title).keys)
1709
- assert_equal(%w( title author_name type id approved ), topics(:first).attributes(:only => [ :title, :id, :type, :approved, :author_name ]).keys)
1710
- end
1711
-
1712
1883
  def test_type_name_with_module_should_handle_beginning
1713
1884
  assert_equal 'ActiveRecord::Person', ActiveRecord::Base.send(:type_name_with_module, 'Person')
1714
1885
  assert_equal '::Person', ActiveRecord::Base.send(:type_name_with_module, '::Person')
@@ -1721,22 +1892,18 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1721
1892
  def test_inspect_class
1722
1893
  assert_equal 'ActiveRecord::Base', ActiveRecord::Base.inspect
1723
1894
  assert_equal 'LoosePerson(abstract)', LoosePerson.inspect
1724
- unless ActiveRecord::Base.connection.servertype.class.name.include?('::IBM_IDS')
1725
1895
  assert_match(/^Topic\(id: integer, title: string/, Topic.inspect)
1726
- else
1727
- assert_match(/^Topic\(id: serial, title: string/, Topic.inspect)
1728
- end
1729
1896
  end
1730
-
1897
+
1731
1898
  def test_inspect_instance
1732
1899
  topic = topics(:first)
1733
1900
  assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, type: nil>), topic.inspect
1734
1901
  end
1735
-
1902
+
1736
1903
  def test_inspect_new_instance
1737
1904
  assert_match /Topic id: nil/, Topic.new.inspect
1738
1905
  end
1739
-
1906
+
1740
1907
  def test_inspect_limited_select_instance
1741
1908
  assert_equal %(#<Topic id: 1>), Topic.find(:first, :select => 'id', :conditions => 'id = 1').inspect
1742
1909
  assert_equal %(#<Topic id: 1, title: "The First Topic">), Topic.find(:first, :select => 'id, title', :conditions => 'id = 1').inspect
@@ -1745,11 +1912,11 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1745
1912
  def test_inspect_class_without_table
1746
1913
  assert_equal "NonExistentTable(Table doesn't exist)", NonExistentTable.inspect
1747
1914
  end
1748
-
1915
+
1749
1916
  def test_attribute_for_inspect
1750
1917
  t = topics(:first)
1751
1918
  t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
1752
-
1919
+
1753
1920
  assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on)
1754
1921
  assert_equal '"The First Topic Now Has A Title With\nNewlines And M..."', t.attribute_for_inspect(:title)
1755
1922
  end
@@ -1758,4 +1925,57 @@ class IBMDBBasicsTest < Test::Unit::TestCase
1758
1925
  assert_kind_of Reply, topics(:first).becomes(Reply)
1759
1926
  assert_equal "The First Topic", topics(:first).becomes(Reply).title
1760
1927
  end
1928
+
1929
+ def test_silence_sets_log_level_to_error_in_block
1930
+ original_logger = ActiveRecord::Base.logger
1931
+ log = StringIO.new
1932
+ ActiveRecord::Base.logger = Logger.new(log)
1933
+ ActiveRecord::Base.logger.level = Logger::DEBUG
1934
+ ActiveRecord::Base.silence do
1935
+ ActiveRecord::Base.logger.warn "warn"
1936
+ ActiveRecord::Base.logger.error "error"
1937
+ end
1938
+ assert_equal "error\n", log.string
1939
+ ensure
1940
+ ActiveRecord::Base.logger = original_logger
1941
+ end
1942
+
1943
+ def test_silence_sets_log_level_back_to_level_before_yield
1944
+ original_logger = ActiveRecord::Base.logger
1945
+ log = StringIO.new
1946
+ ActiveRecord::Base.logger = Logger.new(log)
1947
+ ActiveRecord::Base.logger.level = Logger::WARN
1948
+ ActiveRecord::Base.silence do
1949
+ end
1950
+ assert_equal Logger::WARN, ActiveRecord::Base.logger.level
1951
+ ensure
1952
+ ActiveRecord::Base.logger = original_logger
1953
+ end
1954
+
1955
+ def test_benchmark_with_log_level
1956
+ original_logger = ActiveRecord::Base.logger
1957
+ log = StringIO.new
1958
+ ActiveRecord::Base.logger = Logger.new(log)
1959
+ ActiveRecord::Base.logger.level = Logger::WARN
1960
+ ActiveRecord::Base.benchmark("Debug Topic Count", Logger::DEBUG) { Topic.count }
1961
+ ActiveRecord::Base.benchmark("Warn Topic Count", Logger::WARN) { Topic.count }
1962
+ ActiveRecord::Base.benchmark("Error Topic Count", Logger::ERROR) { Topic.count }
1963
+ assert_no_match /Debug Topic Count/, log.string
1964
+ assert_match /Warn Topic Count/, log.string
1965
+ assert_match /Error Topic Count/, log.string
1966
+ ensure
1967
+ ActiveRecord::Base.logger = original_logger
1968
+ end
1969
+
1970
+ def test_benchmark_with_use_silence
1971
+ original_logger = ActiveRecord::Base.logger
1972
+ log = StringIO.new
1973
+ ActiveRecord::Base.logger = Logger.new(log)
1974
+ ActiveRecord::Base.benchmark("Logging", Logger::DEBUG, true) { ActiveRecord::Base.logger.debug "Loud" }
1975
+ ActiveRecord::Base.benchmark("Logging", Logger::DEBUG, false) { ActiveRecord::Base.logger.debug "Quiet" }
1976
+ assert_no_match /Loud/, log.string
1977
+ assert_match /Quiet/, log.string
1978
+ ensure
1979
+ ActiveRecord::Base.logger = original_logger
1980
+ end
1761
1981
  end