ibm_db 0.9.5 → 0.10.0

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 (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