db2 2.5.6 → 2.5.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGES +17 -0
  2. data/README +79 -141
  3. data/ext/extconf.rb +75 -14
  4. metadata +32 -68
  5. data/.gitignore +0 -1
  6. data/LICENSE +0 -18
  7. data/ParameterizedQueries README +0 -39
  8. data/ext/Makefile.nt32 +0 -181
  9. data/ext/ibm_db.c +0 -11166
  10. data/ext/ruby_ibm_db.h +0 -236
  11. data/ext/ruby_ibm_db_cli.c +0 -738
  12. data/ext/ruby_ibm_db_cli.h +0 -431
  13. data/init.rb +0 -42
  14. data/lib/IBM_DB.rb +0 -2
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +0 -2558
  16. data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +0 -1965
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +0 -328
  18. data/test/cases/adapter_test.rb +0 -202
  19. data/test/cases/associations/belongs_to_associations_test.rb +0 -486
  20. data/test/cases/associations/cascaded_eager_loading_test.rb +0 -183
  21. data/test/cases/associations/eager_test.rb +0 -862
  22. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -917
  23. data/test/cases/associations/has_many_through_associations_test.rb +0 -461
  24. data/test/cases/associations/join_model_test.rb +0 -793
  25. data/test/cases/attribute_methods_test.rb +0 -621
  26. data/test/cases/base_test.rb +0 -1486
  27. data/test/cases/calculations_test.rb +0 -362
  28. data/test/cases/finder_test.rb +0 -1088
  29. data/test/cases/fixtures_test.rb +0 -684
  30. data/test/cases/migration_test.rb +0 -2014
  31. data/test/cases/schema_dumper_test.rb +0 -232
  32. data/test/cases/validations/uniqueness_validation_test.rb +0 -283
  33. data/test/connections/native_ibm_db/connection.rb +0 -42
  34. data/test/ibm_db_test.rb +0 -25
  35. data/test/models/warehouse_thing.rb +0 -5
  36. data/test/schema/i5/ibm_db_specific_schema.rb +0 -135
  37. data/test/schema/ids/ibm_db_specific_schema.rb +0 -138
  38. data/test/schema/luw/ibm_db_specific_schema.rb +0 -135
  39. data/test/schema/schema.rb +0 -647
  40. data/test/schema/zOS/ibm_db_specific_schema.rb +0 -206
@@ -1,1486 +0,0 @@
1
- require "cases/helper"
2
- require 'models/post'
3
- require 'models/author'
4
- require 'models/topic'
5
- require 'models/reply'
6
- require 'models/category'
7
- require 'models/company'
8
- require 'models/customer'
9
- require 'models/developer'
10
- require 'models/project'
11
- require 'models/default'
12
- require 'models/auto_id'
13
- require 'models/boolean'
14
- require 'models/column_name'
15
- require 'models/subscriber'
16
- require 'models/keyboard'
17
- require 'models/comment'
18
- require 'models/minimalistic'
19
- require 'models/warehouse_thing'
20
- require 'models/parrot'
21
- require 'models/loose_person'
22
- require 'rexml/document'
23
- require 'active_support/core_ext/exception'
24
-
25
- class Category < ActiveRecord::Base; end
26
- class Categorization < ActiveRecord::Base; end
27
- class Smarts < ActiveRecord::Base; end
28
- class CreditCard < ActiveRecord::Base
29
- class PinNumber < ActiveRecord::Base
30
- class CvvCode < ActiveRecord::Base; end
31
- class SubCvvCode < CvvCode; end
32
- end
33
- class SubPinNumber < PinNumber; end
34
- class Brand < Category; end
35
- end
36
- class MasterCreditCard < ActiveRecord::Base; end
37
- class Post < ActiveRecord::Base; end
38
- class Computer < ActiveRecord::Base; end
39
- class NonExistentTable < ActiveRecord::Base; end
40
- class TestOracleDefault < ActiveRecord::Base; end
41
-
42
- class ReadonlyTitlePost < Post
43
- attr_readonly :title
44
- end
45
-
46
- class Boolean < ActiveRecord::Base; end
47
-
48
- class BasicsTest < ActiveRecord::TestCase
49
- fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, :warehouse_things, :authors, :categorizations, :categories, :posts
50
-
51
- def test_table_exists
52
- assert !NonExistentTable.table_exists?
53
- assert Topic.table_exists?
54
- end
55
-
56
- def test_preserving_date_objects
57
- if current_adapter?(:SybaseAdapter)
58
- # Sybase ctlib does not (yet?) support the date type; use datetime instead.
59
- assert_kind_of(
60
- Time, Topic.find(1).last_read,
61
- "The last_read attribute should be of the Time class"
62
- )
63
- else
64
- # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb)
65
- assert_kind_of(
66
- Date, Topic.find(1).last_read,
67
- "The last_read attribute should be of the Date class"
68
- )
69
- end
70
- end
71
-
72
- def test_use_table_engine_for_quoting_where
73
- relation = Topic.where(Topic.arel_table[:id].eq(1))
74
- engine = relation.table.engine
75
-
76
- fakepool = Class.new(Struct.new(:spec)) {
77
- def with_connection; yield self; end
78
- def connection_pool; self; end
79
- def quote_table_name(*args); raise "lol quote_table_name"; end
80
- }
81
-
82
- relation.table.engine = fakepool.new(engine.connection_pool.spec)
83
-
84
- error = assert_raises(RuntimeError) { relation.to_a }
85
- assert_match('lol', error.message)
86
- ensure
87
- relation.table.engine = engine
88
- end
89
-
90
- def test_preserving_time_objects
91
- assert_kind_of(
92
- Time, Topic.find(1).bonus_time,
93
- "The bonus_time attribute should be of the Time class"
94
- )
95
-
96
- assert_kind_of(
97
- Time, Topic.find(1).written_on,
98
- "The written_on attribute should be of the Time class"
99
- )
100
-
101
- # For adapters which support microsecond resolution.
102
- if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:SQLiteAdapter)
103
- assert_equal 11, Topic.find(1).written_on.sec
104
- assert_equal 223300, Topic.find(1).written_on.usec
105
- assert_equal 9900, Topic.find(2).written_on.usec
106
- end
107
- end
108
-
109
- def test_preserving_time_objects_with_local_time_conversion_to_default_timezone_utc
110
- with_env_tz 'America/New_York' do
111
- with_active_record_default_timezone :utc do
112
- time = Time.local(2000)
113
- topic = Topic.create('written_on' => time)
114
- saved_time = Topic.find(topic.id).written_on
115
- assert_equal time, saved_time
116
- assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "EST"], time.to_a
117
- assert_equal [0, 0, 5, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
118
- end
119
- end
120
- end
121
-
122
- def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_utc
123
- with_env_tz 'America/New_York' do
124
- with_active_record_default_timezone :utc do
125
- Time.use_zone 'Central Time (US & Canada)' do
126
- time = Time.zone.local(2000)
127
- topic = Topic.create('written_on' => time)
128
- saved_time = Topic.find(topic.id).written_on
129
- assert_equal time, saved_time
130
- assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
131
- assert_equal [0, 0, 6, 1, 1, 2000, 6, 1, false, "UTC"], saved_time.to_a
132
- end
133
- end
134
- end
135
- end
136
-
137
- def test_preserving_time_objects_with_utc_time_conversion_to_default_timezone_local
138
- with_env_tz 'America/New_York' do
139
- time = Time.utc(2000)
140
- topic = Topic.create('written_on' => time)
141
- saved_time = Topic.find(topic.id).written_on
142
- assert_equal time, saved_time
143
- assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], time.to_a
144
- assert_equal [0, 0, 19, 31, 12, 1999, 5, 365, false, "EST"], saved_time.to_a
145
- end
146
- end
147
-
148
- def test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_local
149
- with_env_tz 'America/New_York' do
150
- with_active_record_default_timezone :local do
151
- Time.use_zone 'Central Time (US & Canada)' do
152
- time = Time.zone.local(2000)
153
- topic = Topic.create('written_on' => time)
154
- saved_time = Topic.find(topic.id).written_on
155
- assert_equal time, saved_time
156
- assert_equal [0, 0, 0, 1, 1, 2000, 6, 1, false, "CST"], time.to_a
157
- assert_equal [0, 0, 1, 1, 1, 2000, 6, 1, false, "EST"], saved_time.to_a
158
- end
159
- end
160
- end
161
- end
162
-
163
- def test_custom_mutator
164
- topic = Topic.find(1)
165
- # This mutator is protected in the class definition
166
- topic.send(:approved=, true)
167
- assert topic.instance_variable_get("@custom_approved")
168
- end
169
-
170
- def test_initialize_with_attributes
171
- topic = Topic.new({
172
- "title" => "initialized from attributes", "written_on" => "2003-12-12 23:23"
173
- })
174
-
175
- assert_equal("initialized from attributes", topic.title)
176
- end
177
-
178
- def test_initialize_with_invalid_attribute
179
- begin
180
- topic = Topic.new({ "title" => "test",
181
- "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"})
182
- rescue ActiveRecord::MultiparameterAssignmentErrors => ex
183
- assert_equal(1, ex.errors.size)
184
- assert_equal("last_read", ex.errors[0].attribute)
185
- end
186
- end
187
-
188
- def test_load
189
- topics = Topic.find(:all, :order => 'id')
190
- assert_equal(4, topics.size)
191
- assert_equal(topics(:first).title, topics.first.title)
192
- end
193
-
194
- def test_load_with_condition
195
- topics = Topic.find(:all, :conditions => "author_name = 'Mary'")
196
-
197
- assert_equal(1, topics.size)
198
- assert_equal(topics(:second).title, topics.first.title)
199
- end
200
-
201
- GUESSED_CLASSES = [Category, Smarts, CreditCard, CreditCard::PinNumber, CreditCard::PinNumber::CvvCode, CreditCard::SubPinNumber, CreditCard::Brand, MasterCreditCard]
202
-
203
- def test_table_name_guesses
204
- assert_equal "topics", Topic.table_name
205
-
206
- assert_equal "categories", Category.table_name
207
- assert_equal "smarts", Smarts.table_name
208
- assert_equal "credit_cards", CreditCard.table_name
209
- assert_equal "credit_card_pin_numbers", CreditCard::PinNumber.table_name
210
- assert_equal "credit_card_pin_number_cvv_codes", CreditCard::PinNumber::CvvCode.table_name
211
- assert_equal "credit_card_pin_numbers", CreditCard::SubPinNumber.table_name
212
- assert_equal "categories", CreditCard::Brand.table_name
213
- assert_equal "master_credit_cards", MasterCreditCard.table_name
214
- ensure
215
- GUESSED_CLASSES.each(&:reset_table_name)
216
- end
217
-
218
- def test_singular_table_name_guesses
219
- ActiveRecord::Base.pluralize_table_names = false
220
- GUESSED_CLASSES.each(&:reset_table_name)
221
-
222
- assert_equal "category", Category.table_name
223
- assert_equal "smarts", Smarts.table_name
224
- assert_equal "credit_card", CreditCard.table_name
225
- assert_equal "credit_card_pin_number", CreditCard::PinNumber.table_name
226
- assert_equal "credit_card_pin_number_cvv_code", CreditCard::PinNumber::CvvCode.table_name
227
- assert_equal "credit_card_pin_number", CreditCard::SubPinNumber.table_name
228
- assert_equal "category", CreditCard::Brand.table_name
229
- assert_equal "master_credit_card", MasterCreditCard.table_name
230
- ensure
231
- ActiveRecord::Base.pluralize_table_names = true
232
- GUESSED_CLASSES.each(&:reset_table_name)
233
- end
234
-
235
- def test_table_name_guesses_with_prefixes_and_suffixes
236
- ActiveRecord::Base.table_name_prefix = "test_"
237
- Category.reset_table_name
238
- assert_equal "test_categories", Category.table_name
239
- ActiveRecord::Base.table_name_suffix = "_test"
240
- Category.reset_table_name
241
- assert_equal "test_categories_test", Category.table_name
242
- ActiveRecord::Base.table_name_prefix = ""
243
- Category.reset_table_name
244
- assert_equal "categories_test", Category.table_name
245
- ActiveRecord::Base.table_name_suffix = ""
246
- Category.reset_table_name
247
- assert_equal "categories", Category.table_name
248
- ensure
249
- ActiveRecord::Base.table_name_prefix = ""
250
- ActiveRecord::Base.table_name_suffix = ""
251
- GUESSED_CLASSES.each(&:reset_table_name)
252
- end
253
-
254
- def test_singular_table_name_guesses_with_prefixes_and_suffixes
255
- ActiveRecord::Base.pluralize_table_names = false
256
-
257
- ActiveRecord::Base.table_name_prefix = "test_"
258
- Category.reset_table_name
259
- assert_equal "test_category", Category.table_name
260
- ActiveRecord::Base.table_name_suffix = "_test"
261
- Category.reset_table_name
262
- assert_equal "test_category_test", Category.table_name
263
- ActiveRecord::Base.table_name_prefix = ""
264
- Category.reset_table_name
265
- assert_equal "category_test", Category.table_name
266
- ActiveRecord::Base.table_name_suffix = ""
267
- Category.reset_table_name
268
- assert_equal "category", Category.table_name
269
- ensure
270
- ActiveRecord::Base.pluralize_table_names = true
271
- ActiveRecord::Base.table_name_prefix = ""
272
- ActiveRecord::Base.table_name_suffix = ""
273
- GUESSED_CLASSES.each(&:reset_table_name)
274
- end
275
-
276
- def test_table_name_guesses_with_inherited_prefixes_and_suffixes
277
- GUESSED_CLASSES.each(&:reset_table_name)
278
-
279
- CreditCard.table_name_prefix = "test_"
280
- CreditCard.reset_table_name
281
- Category.reset_table_name
282
- assert_equal "test_credit_cards", CreditCard.table_name
283
- assert_equal "categories", Category.table_name
284
- CreditCard.table_name_suffix = "_test"
285
- CreditCard.reset_table_name
286
- Category.reset_table_name
287
- assert_equal "test_credit_cards_test", CreditCard.table_name
288
- assert_equal "categories", Category.table_name
289
- CreditCard.table_name_prefix = ""
290
- CreditCard.reset_table_name
291
- Category.reset_table_name
292
- assert_equal "credit_cards_test", CreditCard.table_name
293
- assert_equal "categories", Category.table_name
294
- CreditCard.table_name_suffix = ""
295
- CreditCard.reset_table_name
296
- Category.reset_table_name
297
- assert_equal "credit_cards", CreditCard.table_name
298
- assert_equal "categories", Category.table_name
299
- ensure
300
- CreditCard.table_name_prefix = ""
301
- CreditCard.table_name_suffix = ""
302
- GUESSED_CLASSES.each(&:reset_table_name)
303
- end
304
-
305
-
306
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
307
- def test_update_all_with_order_and_limit
308
- assert_equal 1, Topic.update_all("content = 'bulk updated!'", nil, :limit => 1, :order => 'id DESC')
309
- end
310
- end
311
-
312
- def test_null_fields
313
- assert_nil Topic.find(1).parent_id
314
- assert_nil Topic.create("title" => "Hey you").parent_id
315
- end
316
-
317
- def test_default_values
318
- topic = Topic.new
319
- assert topic.approved?
320
- assert_nil topic.written_on
321
- assert_nil topic.bonus_time
322
- assert_nil topic.last_read
323
-
324
- topic.save
325
-
326
- topic = Topic.find(topic.id)
327
- assert topic.approved?
328
- assert_nil topic.last_read
329
-
330
- # Oracle has some funky default handling, so it requires a bit of
331
- # extra testing. See ticket #2788.
332
- if current_adapter?(:OracleAdapter)
333
- test = TestOracleDefault.new
334
- assert_equal "X", test.test_char
335
- assert_equal "hello", test.test_string
336
- assert_equal 3, test.test_int
337
- end
338
- end
339
-
340
- # Oracle, and Sybase do not have a TIME datatype.
341
- unless current_adapter?(:OracleAdapter, :SybaseAdapter)
342
- def test_utc_as_time_zone
343
- Topic.default_timezone = :utc
344
- attributes = { "bonus_time" => "5:42:00AM" }
345
- topic = Topic.find(1)
346
- topic.attributes = attributes
347
- assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
348
- Topic.default_timezone = :local
349
- end
350
-
351
- def test_utc_as_time_zone_and_new
352
- Topic.default_timezone = :utc
353
- attributes = { "bonus_time(1i)"=>"2000",
354
- "bonus_time(2i)"=>"1",
355
- "bonus_time(3i)"=>"1",
356
- "bonus_time(4i)"=>"10",
357
- "bonus_time(5i)"=>"35",
358
- "bonus_time(6i)"=>"50" }
359
- topic = Topic.new(attributes)
360
- assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time
361
- Topic.default_timezone = :local
362
- end
363
- end
364
-
365
- def test_default_values_on_empty_strings
366
- topic = Topic.new
367
- topic.approved = nil
368
- topic.last_read = nil
369
-
370
- topic.save
371
-
372
- topic = Topic.find(topic.id)
373
- assert_nil topic.last_read
374
-
375
- # Sybase adapter does not allow nulls in boolean columns
376
- if current_adapter?(:SybaseAdapter)
377
- assert topic.approved == false
378
- else
379
- assert_nil topic.approved
380
- end
381
- end
382
-
383
- def test_equality
384
- assert_equal Topic.find(1), Topic.find(2).topic
385
- end
386
-
387
- def test_equality_of_new_records
388
- assert_not_equal Topic.new, Topic.new
389
- end
390
-
391
- def test_equality_of_destroyed_records
392
- topic_1 = Topic.new(:title => 'test_1')
393
- topic_1.save
394
- topic_2 = Topic.find(topic_1.id)
395
- topic_1.destroy
396
- assert_equal topic_1, topic_2
397
- assert_equal topic_2, topic_1
398
- end
399
-
400
- def test_hashing
401
- assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ]
402
- end
403
-
404
- def test_readonly_attributes
405
- assert_equal Set.new([ 'title' , 'comments_count' ]), ReadonlyTitlePost.readonly_attributes
406
-
407
- post = ReadonlyTitlePost.create(:title => "cannot change this", :body => "changeable")
408
- post.reload
409
- assert_equal "cannot change this", post.title
410
-
411
- post.update_attributes(:title => "try to change", :body => "changed")
412
- post.reload
413
- assert_equal "cannot change this", post.title
414
- assert_equal "changed", post.body
415
- end
416
-
417
- def test_multiparameter_attributes_on_date
418
- attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" }
419
- topic = Topic.find(1)
420
- topic.attributes = attributes
421
- # note that extra #to_date call allows test to pass for Oracle, which
422
- # treats dates/times the same
423
- assert_date_from_db Date.new(2004, 6, 24), topic.last_read.to_date
424
- end
425
-
426
- def test_multiparameter_attributes_on_date_with_empty_year
427
- attributes = { "last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "24" }
428
- topic = Topic.find(1)
429
- topic.attributes = attributes
430
- # note that extra #to_date call allows test to pass for Oracle, which
431
- # treats dates/times the same
432
- assert_date_from_db Date.new(1, 6, 24), topic.last_read.to_date
433
- end
434
-
435
- def test_multiparameter_attributes_on_date_with_empty_month
436
- attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "24" }
437
- topic = Topic.find(1)
438
- topic.attributes = attributes
439
- # note that extra #to_date call allows test to pass for Oracle, which
440
- # treats dates/times the same
441
- assert_date_from_db Date.new(2004, 1, 24), topic.last_read.to_date
442
- end
443
-
444
- def test_multiparameter_attributes_on_date_with_empty_day
445
- attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "" }
446
- topic = Topic.find(1)
447
- topic.attributes = attributes
448
- # note that extra #to_date call allows test to pass for Oracle, which
449
- # treats dates/times the same
450
- assert_date_from_db Date.new(2004, 6, 1), topic.last_read.to_date
451
- end
452
-
453
- def test_multiparameter_attributes_on_date_with_empty_day_and_year
454
- attributes = { "last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "" }
455
- topic = Topic.find(1)
456
- topic.attributes = attributes
457
- # note that extra #to_date call allows test to pass for Oracle, which
458
- # treats dates/times the same
459
- assert_date_from_db Date.new(1, 6, 1), topic.last_read.to_date
460
- end
461
-
462
- def test_multiparameter_attributes_on_date_with_empty_day_and_month
463
- attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "" }
464
- topic = Topic.find(1)
465
- topic.attributes = attributes
466
- # note that extra #to_date call allows test to pass for Oracle, which
467
- # treats dates/times the same
468
- assert_date_from_db Date.new(2004, 1, 1), topic.last_read.to_date
469
- end
470
-
471
- def test_multiparameter_attributes_on_date_with_empty_year_and_month
472
- attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "24" }
473
- topic = Topic.find(1)
474
- topic.attributes = attributes
475
- # note that extra #to_date call allows test to pass for Oracle, which
476
- # treats dates/times the same
477
- assert_date_from_db Date.new(1, 1, 24), topic.last_read.to_date
478
- end
479
-
480
- def test_multiparameter_attributes_on_date_with_all_empty
481
- attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "" }
482
- topic = Topic.find(1)
483
- topic.attributes = attributes
484
- assert_nil topic.last_read
485
- end
486
-
487
- def test_multiparameter_attributes_on_time
488
- attributes = {
489
- "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
490
- "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
491
- }
492
- topic = Topic.find(1)
493
- topic.attributes = attributes
494
- assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
495
- end
496
-
497
- def test_multiparameter_attributes_on_time_with_old_date
498
- attributes = {
499
- "written_on(1i)" => "1850", "written_on(2i)" => "6", "written_on(3i)" => "24",
500
- "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
501
- }
502
- topic = Topic.find(1)
503
- topic.attributes = attributes
504
- # testing against to_s(:db) representation because either a Time or a DateTime might be returned, depending on platform
505
- assert_equal "1850-06-24 16:24:00", topic.written_on.to_s(:db)
506
- end
507
-
508
- def test_multiparameter_attributes_on_time_with_utc
509
- ActiveRecord::Base.default_timezone = :utc
510
- attributes = {
511
- "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
512
- "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
513
- }
514
- topic = Topic.find(1)
515
- topic.attributes = attributes
516
- assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on
517
- ensure
518
- ActiveRecord::Base.default_timezone = :local
519
- end
520
-
521
- def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes
522
- ActiveRecord::Base.time_zone_aware_attributes = true
523
- ActiveRecord::Base.default_timezone = :utc
524
- Time.zone = ActiveSupport::TimeZone[-28800]
525
- attributes = {
526
- "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
527
- "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
528
- }
529
- topic = Topic.find(1)
530
- topic.attributes = attributes
531
- assert_equal Time.utc(2004, 6, 24, 23, 24, 0), topic.written_on
532
- assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on.time
533
- assert_equal Time.zone, topic.written_on.time_zone
534
- ensure
535
- ActiveRecord::Base.time_zone_aware_attributes = false
536
- ActiveRecord::Base.default_timezone = :local
537
- Time.zone = nil
538
- end
539
-
540
- def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes_false
541
- ActiveRecord::Base.time_zone_aware_attributes = false
542
- Time.zone = ActiveSupport::TimeZone[-28800]
543
- attributes = {
544
- "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
545
- "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
546
- }
547
- topic = Topic.find(1)
548
- topic.attributes = attributes
549
- assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
550
- assert_equal false, topic.written_on.respond_to?(:time_zone)
551
- ensure
552
- Time.zone = nil
553
- end
554
-
555
- def test_multiparameter_attributes_on_time_with_skip_time_zone_conversion_for_attributes
556
- ActiveRecord::Base.time_zone_aware_attributes = true
557
- ActiveRecord::Base.default_timezone = :utc
558
- Time.zone = ActiveSupport::TimeZone[-28800]
559
- Topic.skip_time_zone_conversion_for_attributes = [:written_on]
560
- attributes = {
561
- "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
562
- "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
563
- }
564
- topic = Topic.find(1)
565
- topic.attributes = attributes
566
- assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on
567
- assert_equal false, topic.written_on.respond_to?(:time_zone)
568
- ensure
569
- ActiveRecord::Base.time_zone_aware_attributes = false
570
- ActiveRecord::Base.default_timezone = :local
571
- Time.zone = nil
572
- Topic.skip_time_zone_conversion_for_attributes = []
573
- end
574
-
575
- # Oracle, and Sybase do not have a TIME datatype.
576
- unless current_adapter?(:OracleAdapter, :SybaseAdapter)
577
- def test_multiparameter_attributes_on_time_only_column_with_time_zone_aware_attributes_does_not_do_time_zone_conversion
578
- ActiveRecord::Base.time_zone_aware_attributes = true
579
- ActiveRecord::Base.default_timezone = :utc
580
- Time.zone = ActiveSupport::TimeZone[-28800]
581
- attributes = {
582
- "bonus_time(1i)" => "2000", "bonus_time(2i)" => "1", "bonus_time(3i)" => "1",
583
- "bonus_time(4i)" => "16", "bonus_time(5i)" => "24"
584
- }
585
- topic = Topic.find(1)
586
- topic.attributes = attributes
587
- assert_equal Time.utc(2000, 1, 1, 16, 24, 0), topic.bonus_time
588
- assert topic.bonus_time.utc?
589
- ensure
590
- ActiveRecord::Base.time_zone_aware_attributes = false
591
- ActiveRecord::Base.default_timezone = :local
592
- Time.zone = nil
593
- end
594
- end
595
-
596
- def test_multiparameter_attributes_on_time_with_empty_seconds
597
- attributes = {
598
- "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
599
- "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => ""
600
- }
601
- topic = Topic.find(1)
602
- topic.attributes = attributes
603
- assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
604
- end
605
-
606
- def test_multiparameter_assignment_of_aggregation
607
- customer = Customer.new
608
- address = Address.new("The Street", "The City", "The Country")
609
- attributes = { "address(1)" => address.street, "address(2)" => address.city, "address(3)" => address.country }
610
- customer.attributes = attributes
611
- assert_equal address, customer.address
612
- end
613
-
614
- def test_attributes_on_dummy_time
615
- # Oracle, and Sybase do not have a TIME datatype.
616
- return true if current_adapter?(:OracleAdapter, :SybaseAdapter)
617
-
618
- attributes = {
619
- "bonus_time" => "5:42:00AM"
620
- }
621
- topic = Topic.find(1)
622
- topic.attributes = attributes
623
- assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
624
- end
625
-
626
- def test_boolean
627
- b_nil = Boolean.create({ "value" => nil })
628
- nil_id = b_nil.id
629
- b_false = Boolean.create({ "value" => false })
630
- false_id = b_false.id
631
- b_true = Boolean.create({ "value" => true })
632
- true_id = b_true.id
633
-
634
- b_nil = Boolean.find(nil_id)
635
- assert_nil b_nil.value
636
- b_false = Boolean.find(false_id)
637
- assert !b_false.value?
638
- b_true = Boolean.find(true_id)
639
- assert b_true.value?
640
- end
641
-
642
- def test_boolean_cast_from_string
643
- b_blank = Boolean.create({ "value" => "" })
644
- blank_id = b_blank.id
645
- b_false = Boolean.create({ "value" => "0" })
646
- false_id = b_false.id
647
- b_true = Boolean.create({ "value" => "1" })
648
- true_id = b_true.id
649
-
650
- b_blank = Boolean.find(blank_id)
651
- assert_nil b_blank.value
652
- b_false = Boolean.find(false_id)
653
- assert !b_false.value?
654
- b_true = Boolean.find(true_id)
655
- assert b_true.value?
656
- end
657
-
658
- def test_new_record_returns_boolean
659
- assert_equal false, Topic.new.persisted?
660
- assert_equal true, Topic.find(1).persisted?
661
- end
662
-
663
- def test_clone
664
- topic = Topic.find(1)
665
- cloned_topic = nil
666
- assert_nothing_raised { cloned_topic = topic.clone }
667
- assert_equal topic.title, cloned_topic.title
668
- assert !cloned_topic.persisted?
669
-
670
- # test if the attributes have been cloned
671
- topic.title = "a"
672
- cloned_topic.title = "b"
673
- assert_equal "a", topic.title
674
- assert_equal "b", cloned_topic.title
675
-
676
- # test if the attribute values have been cloned
677
- topic.title = {"a" => "b"}
678
- cloned_topic = topic.clone
679
- cloned_topic.title["a"] = "c"
680
- assert_equal "b", topic.title["a"]
681
-
682
- # test if attributes set as part of after_initialize are cloned correctly
683
- assert_equal topic.author_email_address, cloned_topic.author_email_address
684
-
685
- # test if saved clone object differs from original
686
- cloned_topic.save
687
- assert cloned_topic.persisted?
688
- assert_not_equal cloned_topic.id, topic.id
689
- end
690
-
691
- def test_clone_with_aggregate_of_same_name_as_attribute
692
- dev = DeveloperWithAggregate.find(1)
693
- assert_kind_of DeveloperSalary, dev.salary
694
-
695
- clone = nil
696
- assert_nothing_raised { clone = dev.clone }
697
- assert_kind_of DeveloperSalary, clone.salary
698
- assert_equal dev.salary.amount, clone.salary.amount
699
- assert !clone.persisted?
700
-
701
- # test if the attributes have been cloned
702
- original_amount = clone.salary.amount
703
- dev.salary.amount = 1
704
- assert_equal original_amount, clone.salary.amount
705
-
706
- assert clone.save
707
- assert clone.persisted?
708
- assert_not_equal clone.id, dev.id
709
- end
710
-
711
- def test_clone_does_not_clone_associations
712
- author = authors(:david)
713
- assert_not_equal [], author.posts
714
-
715
- author_clone = author.clone
716
- assert_equal [], author_clone.posts
717
- end
718
-
719
- def test_clone_preserves_subtype
720
- clone = nil
721
- assert_nothing_raised { clone = Company.find(3).clone }
722
- assert_kind_of Client, clone
723
- end
724
-
725
- def test_clone_of_new_object_with_defaults
726
- developer = Developer.new
727
- assert !developer.name_changed?
728
- assert !developer.salary_changed?
729
-
730
- cloned_developer = developer.clone
731
- assert !cloned_developer.name_changed?
732
- assert !cloned_developer.salary_changed?
733
- end
734
-
735
- def test_clone_of_new_object_marks_attributes_as_dirty
736
- developer = Developer.new :name => 'Bjorn', :salary => 100000
737
- assert developer.name_changed?
738
- assert developer.salary_changed?
739
-
740
- cloned_developer = developer.clone
741
- assert cloned_developer.name_changed?
742
- assert cloned_developer.salary_changed?
743
- end
744
-
745
- def test_clone_of_new_object_marks_as_dirty_only_changed_attributes
746
- developer = Developer.new :name => 'Bjorn'
747
- assert developer.name_changed? # obviously
748
- assert !developer.salary_changed? # attribute has non-nil default value, so treated as not changed
749
-
750
- cloned_developer = developer.clone
751
- assert cloned_developer.name_changed?
752
- assert !cloned_developer.salary_changed? # ... and cloned instance should behave same
753
- end
754
-
755
- def test_clone_of_saved_object_marks_attributes_as_dirty
756
- developer = Developer.create! :name => 'Bjorn', :salary => 100000
757
- assert !developer.name_changed?
758
- assert !developer.salary_changed?
759
-
760
- cloned_developer = developer.clone
761
- assert cloned_developer.name_changed? # both attributes differ from defaults
762
- assert cloned_developer.salary_changed?
763
- end
764
-
765
- def test_clone_of_saved_object_marks_as_dirty_only_changed_attributes
766
- developer = Developer.create! :name => 'Bjorn'
767
- assert !developer.name_changed? # both attributes of saved object should be threated as not changed
768
- assert !developer.salary_changed?
769
-
770
- cloned_developer = developer.clone
771
- assert cloned_developer.name_changed? # ... but on cloned object should be
772
- assert !cloned_developer.salary_changed? # ... BUT salary has non-nil default which should be threated as not changed on cloned instance
773
- end
774
-
775
- def test_bignum
776
- company = Company.find(1)
777
- company.rating = 2147483647
778
- company.save
779
- company = Company.find(1)
780
- assert_equal 2147483647, company.rating
781
- end
782
-
783
- # TODO: extend defaults tests to other databases!
784
- if current_adapter?(:PostgreSQLAdapter)
785
- def test_default
786
- default = Default.new
787
-
788
- # fixed dates / times
789
- assert_equal Date.new(2004, 1, 1), default.fixed_date
790
- assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time
791
-
792
- # char types
793
- assert_equal 'Y', default.char1
794
- assert_equal 'a varchar field', default.char2
795
- assert_equal 'a text field', default.char3
796
- end
797
-
798
- class Geometric < ActiveRecord::Base; end
799
- def test_geometric_content
800
-
801
- # accepted format notes:
802
- # ()'s aren't required
803
- # values can be a mix of float or integer
804
-
805
- g = Geometric.new(
806
- :a_point => '(5.0, 6.1)',
807
- #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
808
- :a_line_segment => '(2.0, 3), (5.5, 7.0)',
809
- :a_box => '2.0, 3, 5.5, 7.0',
810
- :a_path => '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]', # [ ] is an open path
811
- :a_polygon => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))',
812
- :a_circle => '<(5.3, 10.4), 2>'
813
- )
814
-
815
- assert g.save
816
-
817
- # Reload and check that we have all the geometric attributes.
818
- h = Geometric.find(g.id)
819
-
820
- assert_equal '(5,6.1)', h.a_point
821
- assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
822
- assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner
823
- assert_equal '[(2,3),(5.5,7),(8.5,11)]', h.a_path
824
- assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
825
- assert_equal '<(5.3,10.4),2>', h.a_circle
826
-
827
- # use a geometric function to test for an open path
828
- objs = Geometric.find_by_sql ["select isopen(a_path) from geometrics where id = ?", g.id]
829
- assert_equal objs[0].isopen, 't'
830
-
831
- # test alternate formats when defining the geometric types
832
-
833
- g = Geometric.new(
834
- :a_point => '5.0, 6.1',
835
- #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
836
- :a_line_segment => '((2.0, 3), (5.5, 7.0))',
837
- :a_box => '(2.0, 3), (5.5, 7.0)',
838
- :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path
839
- :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0',
840
- :a_circle => '((5.3, 10.4), 2)'
841
- )
842
-
843
- assert g.save
844
-
845
- # Reload and check that we have all the geometric attributes.
846
- h = Geometric.find(g.id)
847
-
848
- assert_equal '(5,6.1)', h.a_point
849
- assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
850
- assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner
851
- assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path
852
- assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
853
- assert_equal '<(5.3,10.4),2>', h.a_circle
854
-
855
- # use a geometric function to test for an closed path
856
- objs = Geometric.find_by_sql ["select isclosed(a_path) from geometrics where id = ?", g.id]
857
- assert_equal objs[0].isclosed, 't'
858
- end
859
- end
860
-
861
- class NumericData < ActiveRecord::Base
862
- self.table_name = 'numeric_data'
863
- end
864
-
865
- def test_numeric_fields
866
- m = NumericData.new(
867
- :bank_balance => 1586.43,
868
- :big_bank_balance => BigDecimal("1000234000567.95"),
869
- :world_population => 6000000000,
870
- :my_house_population => 3
871
- )
872
- assert m.save
873
-
874
- m1 = NumericData.find(m.id)
875
- assert_not_nil m1
876
-
877
- # As with migration_test.rb, we should make world_population >= 2**62
878
- # to cover 64-bit platforms and test it is a Bignum, but the main thing
879
- # is that it's an Integer.
880
- unless current_adapter?(:IBM_DBAdapter)
881
- assert_kind_of Integer, m1.world_population
882
- else
883
- assert_kind_of BigDecimal, m1.world_population
884
- end
885
- assert_equal 6000000000, m1.world_population
886
- unless current_adapter?(:IBM_DBAdapter)
887
- assert_kind_of Fixnum, m1.my_house_population
888
- else
889
- assert_kind_of BigDecimal, m1.my_house_population
890
- end
891
- assert_equal 3, m1.my_house_population
892
-
893
- assert_kind_of BigDecimal, m1.bank_balance
894
- assert_equal BigDecimal("1586.43"), m1.bank_balance
895
-
896
- assert_kind_of BigDecimal, m1.big_bank_balance
897
- assert_equal BigDecimal("1000234000567.95"), m1.big_bank_balance
898
- end
899
-
900
- def test_auto_id
901
- auto = AutoId.new
902
- auto.save
903
- assert(auto.id > 0)
904
- end
905
-
906
- def quote_column_name(name)
907
- "<#{name}>"
908
- end
909
-
910
- def test_quote_keys
911
- ar = AutoId.new
912
- source = {"foo" => "bar", "baz" => "quux"}
913
- actual = ar.send(:quote_columns, self, source)
914
- inverted = actual.invert
915
- assert_equal("<foo>", inverted["bar"])
916
- assert_equal("<baz>", inverted["quux"])
917
- end
918
-
919
- def test_sql_injection_via_find
920
- assert_raise(ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid) do
921
- Topic.find("123456 OR id > 0")
922
- end
923
- end
924
-
925
- def test_column_name_properly_quoted
926
- col_record = ColumnName.new
927
- col_record.references = 40
928
- assert col_record.save
929
- col_record.references = 41
930
- assert col_record.save
931
- assert_not_nil c2 = ColumnName.find(col_record.id)
932
- assert_equal(41, c2.references)
933
- end
934
-
935
- def test_quoting_arrays
936
- replies = Reply.find(:all, :conditions => [ "id IN (?)", topics(:first).replies.collect(&:id) ])
937
- assert_equal topics(:first).replies.size, replies.size
938
-
939
- replies = Reply.find(:all, :conditions => [ "id IN (?)", [] ])
940
- assert_equal 0, replies.size
941
- end
942
-
943
- MyObject = Struct.new :attribute1, :attribute2
944
-
945
- def test_serialized_attribute
946
- Topic.serialize("content", MyObject)
947
-
948
- myobj = MyObject.new('value1', 'value2')
949
- topic = Topic.create("content" => myobj)
950
- assert_equal(myobj, topic.content)
951
-
952
- topic.reload
953
- assert_equal(myobj, topic.content)
954
- end
955
-
956
- def test_serialized_time_attribute
957
- myobj = Time.local(2008,1,1,1,0)
958
- topic = Topic.create("content" => myobj).reload
959
- assert_equal(myobj, topic.content)
960
- end
961
-
962
- def test_serialized_string_attribute
963
- myobj = "Yes"
964
- topic = Topic.create("content" => myobj).reload
965
- assert_equal(myobj, topic.content)
966
- end
967
-
968
- def test_nil_serialized_attribute_with_class_constraint
969
- myobj = MyObject.new('value1', 'value2')
970
- topic = Topic.new
971
- assert_nil topic.content
972
- end
973
-
974
- def test_should_raise_exception_on_serialized_attribute_with_type_mismatch
975
- myobj = MyObject.new('value1', 'value2')
976
- topic = Topic.new(:content => myobj)
977
- assert topic.save
978
- Topic.serialize(:content, Hash)
979
- assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content }
980
- ensure
981
- Topic.serialize(:content)
982
- end
983
-
984
- def test_serialized_attribute_with_class_constraint
985
- settings = { "color" => "blue" }
986
- Topic.serialize(:content, Hash)
987
- topic = Topic.new(:content => settings)
988
- assert topic.save
989
- assert_equal(settings, Topic.find(topic.id).content)
990
- ensure
991
- Topic.serialize(:content)
992
- end
993
-
994
- def test_quote
995
- author_name = "\\ \001 ' \n \\n \""
996
- topic = Topic.create('author_name' => author_name)
997
- assert_equal author_name, Topic.find(topic.id).author_name
998
- end
999
-
1000
- if RUBY_VERSION < '1.9'
1001
- def test_quote_chars
1002
- with_kcode('UTF8') do
1003
- str = 'The Narrator'
1004
- topic = Topic.create(:author_name => str)
1005
- assert_equal str, topic.author_name
1006
-
1007
- assert_kind_of ActiveSupport::Multibyte.proxy_class, str.mb_chars
1008
- topic = Topic.find_by_author_name(str.mb_chars)
1009
-
1010
- assert_kind_of Topic, topic
1011
- assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars"
1012
- end
1013
- end
1014
- end
1015
-
1016
- def test_toggle_attribute
1017
- assert !topics(:first).approved?
1018
- topics(:first).toggle!(:approved)
1019
- assert topics(:first).approved?
1020
- topic = topics(:first)
1021
- topic.toggle(:approved)
1022
- assert !topic.approved?
1023
- topic.reload
1024
- assert topic.approved?
1025
- end
1026
-
1027
- def test_reload
1028
- t1 = Topic.find(1)
1029
- t2 = Topic.find(1)
1030
- t1.title = "something else"
1031
- t1.save
1032
- t2.reload
1033
- assert_equal t1.title, t2.title
1034
- end
1035
-
1036
- def test_reload_with_exclusive_scope
1037
- dev = DeveloperCalledDavid.first
1038
- dev.update_attributes!( :name => "NotDavid" )
1039
- assert_equal dev, dev.reload
1040
- end
1041
-
1042
- def test_define_attr_method_with_value
1043
- k = Class.new( ActiveRecord::Base )
1044
- k.send(:define_attr_method, :table_name, "foo")
1045
- assert_equal "foo", k.table_name
1046
- end
1047
-
1048
- def test_define_attr_method_with_block
1049
- k = Class.new( ActiveRecord::Base )
1050
- k.send(:define_attr_method, :primary_key) { "sys_" + original_primary_key }
1051
- assert_equal "sys_id", k.primary_key
1052
- end
1053
-
1054
- def test_set_table_name_with_value
1055
- k = Class.new( ActiveRecord::Base )
1056
- k.table_name = "foo"
1057
- assert_equal "foo", k.table_name
1058
- k.set_table_name "bar"
1059
- assert_equal "bar", k.table_name
1060
- end
1061
-
1062
- def test_quoted_table_name_after_set_table_name
1063
- klass = Class.new(ActiveRecord::Base)
1064
-
1065
- klass.set_table_name "foo"
1066
- assert_equal "foo", klass.table_name
1067
- assert_equal klass.connection.quote_table_name("foo"), klass.quoted_table_name
1068
-
1069
- klass.set_table_name "bar"
1070
- assert_equal "bar", klass.table_name
1071
- assert_equal klass.connection.quote_table_name("bar"), klass.quoted_table_name
1072
- end
1073
-
1074
- def test_set_table_name_with_block
1075
- k = Class.new( ActiveRecord::Base )
1076
- k.set_table_name { "ks" }
1077
- assert_equal "ks", k.table_name
1078
- end
1079
-
1080
- def test_set_primary_key_with_value
1081
- k = Class.new( ActiveRecord::Base )
1082
- k.primary_key = "foo"
1083
- assert_equal "foo", k.primary_key
1084
- k.set_primary_key "bar"
1085
- assert_equal "bar", k.primary_key
1086
- end
1087
-
1088
- def test_set_primary_key_with_block
1089
- k = Class.new( ActiveRecord::Base )
1090
- k.set_primary_key { "sys_" + original_primary_key }
1091
- assert_equal "sys_id", k.primary_key
1092
- end
1093
-
1094
- def test_set_inheritance_column_with_value
1095
- k = Class.new( ActiveRecord::Base )
1096
- k.inheritance_column = "foo"
1097
- assert_equal "foo", k.inheritance_column
1098
- k.set_inheritance_column "bar"
1099
- assert_equal "bar", k.inheritance_column
1100
- end
1101
-
1102
- def test_set_inheritance_column_with_block
1103
- k = Class.new( ActiveRecord::Base )
1104
- k.set_inheritance_column { original_inheritance_column + "_id" }
1105
- assert_equal "type_id", k.inheritance_column
1106
- end
1107
-
1108
- def test_count_with_join
1109
- res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'"
1110
-
1111
- res2 = Post.count(:conditions => "posts.#{QUOTED_TYPE} = 'Post'", :joins => "LEFT JOIN comments ON posts.id=comments.post_id")
1112
- assert_equal res, res2
1113
-
1114
- res3 = nil
1115
- assert_nothing_raised do
1116
- res3 = Post.count(:conditions => "posts.#{QUOTED_TYPE} = 'Post'",
1117
- :joins => "LEFT JOIN comments ON posts.id=comments.post_id")
1118
- end
1119
- assert_equal res, res3
1120
-
1121
- res4 = Post.count_by_sql "SELECT COUNT(p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
1122
- res5 = nil
1123
- assert_nothing_raised do
1124
- res5 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
1125
- :joins => "p, comments co",
1126
- :select => "p.id")
1127
- end
1128
-
1129
- assert_equal res4, res5
1130
-
1131
- 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"
1132
- res7 = nil
1133
- assert_nothing_raised do
1134
- res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
1135
- :joins => "p, comments co",
1136
- :select => "p.id",
1137
- :distinct => true)
1138
- end
1139
- assert_equal res6, res7
1140
- end
1141
-
1142
- def test_interpolate_sql
1143
- assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo@bar') }
1144
- assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar) baz') }
1145
- assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar} baz') }
1146
- end
1147
-
1148
- def test_scoped_find_conditions
1149
- scoped_developers = Developer.send(:with_scope, :find => { :conditions => 'salary > 90000' }) do
1150
- Developer.find(:all, :conditions => 'id < 5')
1151
- end
1152
- assert !scoped_developers.include?(developers(:david)) # David's salary is less than 90,000
1153
- assert_equal 3, scoped_developers.size
1154
- end
1155
-
1156
- def test_scoped_find_limit_offset
1157
- scoped_developers = Developer.send(:with_scope, :find => { :limit => 3, :offset => 2 }) do
1158
- Developer.find(:all, :order => 'id')
1159
- end
1160
- assert !scoped_developers.include?(developers(:david))
1161
- assert !scoped_developers.include?(developers(:jamis))
1162
- assert_equal 3, scoped_developers.size
1163
-
1164
- # Test without scoped find conditions to ensure we get the whole thing
1165
- developers = Developer.find(:all, :order => 'id')
1166
- assert_equal Developer.count, developers.size
1167
- end
1168
-
1169
- def test_scoped_find_order
1170
- # Test order in scope
1171
- scoped_developers = Developer.send(:with_scope, :find => { :limit => 1, :order => 'salary DESC' }) do
1172
- Developer.find(:all)
1173
- end
1174
- assert_equal 'Jamis', scoped_developers.first.name
1175
- assert scoped_developers.include?(developers(:jamis))
1176
- # Test scope without order and order in find
1177
- scoped_developers = Developer.send(:with_scope, :find => { :limit => 1 }) do
1178
- Developer.find(:all, :order => 'salary DESC')
1179
- end
1180
- # Test scope order + find order, order has priority
1181
- scoped_developers = Developer.send(:with_scope, :find => { :limit => 3, :order => 'id DESC' }) do
1182
- Developer.find(:all, :order => 'salary ASC')
1183
- end
1184
- assert scoped_developers.include?(developers(:poor_jamis))
1185
- assert ! scoped_developers.include?(developers(:david))
1186
- assert ! scoped_developers.include?(developers(:jamis))
1187
- assert_equal 3, scoped_developers.size
1188
-
1189
- # Test without scoped find conditions to ensure we get the right thing
1190
- assert ! scoped_developers.include?(Developer.find(1))
1191
- assert scoped_developers.include?(Developer.find(11))
1192
- end
1193
-
1194
- def test_scoped_find_limit_offset_including_has_many_association
1195
- topics = Topic.send(:with_scope, :find => {:limit => 1, :offset => 1, :include => :replies}) do
1196
- Topic.find(:all, :order => "topics.id")
1197
- end
1198
- assert_equal 1, topics.size
1199
- assert_equal 2, topics.first.id
1200
- end
1201
-
1202
- def test_scoped_find_order_including_has_many_association
1203
- developers = Developer.send(:with_scope, :find => { :order => 'developers.salary DESC', :include => :projects }) do
1204
- Developer.find(:all)
1205
- end
1206
- assert developers.size >= 2
1207
- for i in 1...developers.size
1208
- assert developers[i-1].salary >= developers[i].salary
1209
- end
1210
- end
1211
-
1212
- def test_scoped_find_with_group_and_having
1213
- developers = Developer.send(:with_scope, :find => { :group => 'developers.salary', :having => "SUM(salary) > 10000", :select => "SUM(salary) as salary" }) do
1214
- Developer.find(:all)
1215
- end
1216
- assert_equal 3, developers.size
1217
- end
1218
-
1219
- def test_find_last
1220
- last = Developer.find :last
1221
- assert_equal last, Developer.find(:first, :order => 'id desc')
1222
- end
1223
-
1224
- def test_last
1225
- assert_equal Developer.find(:first, :order => 'id desc'), Developer.last
1226
- end
1227
-
1228
- def test_all
1229
- developers = Developer.all
1230
- assert_kind_of Array, developers
1231
- assert_equal Developer.find(:all), developers
1232
- end
1233
-
1234
- def test_all_with_conditions
1235
- assert_equal Developer.find(:all, :order => 'id desc'), Developer.order('id desc').all
1236
- end
1237
-
1238
- def test_find_ordered_last
1239
- last = Developer.find :last, :order => 'developers.salary ASC'
1240
- assert_equal last, Developer.find(:all, :order => 'developers.salary ASC').last
1241
- end
1242
-
1243
- def test_find_reverse_ordered_last
1244
- last = Developer.find :last, :order => 'developers.salary DESC'
1245
- assert_equal last, Developer.find(:all, :order => 'developers.salary DESC').last
1246
- end
1247
-
1248
- def test_find_multiple_ordered_last
1249
- last = Developer.find :last, :order => 'developers.name, developers.salary DESC'
1250
- assert_equal last, Developer.find(:all, :order => 'developers.name, developers.salary DESC').last
1251
- end
1252
-
1253
- def test_find_keeps_multiple_order_values
1254
- combined = Developer.find(:all, :order => 'developers.name, developers.salary')
1255
- assert_equal combined, Developer.find(:all, :order => ['developers.name', 'developers.salary'])
1256
- end
1257
-
1258
- def test_find_keeps_multiple_group_values
1259
- combined = Developer.find(:all, :group => 'developers.name, developers.salary, developers.id, developers.created_at, developers.updated_at')
1260
- assert_equal combined, Developer.find(:all, :group => ['developers.name', 'developers.salary', 'developers.id', 'developers.created_at', 'developers.updated_at'])
1261
- end
1262
-
1263
- def test_find_symbol_ordered_last
1264
- last = Developer.find :last, :order => :salary
1265
- assert_equal last, Developer.find(:all, :order => :salary).last
1266
- end
1267
-
1268
- def test_find_scoped_ordered_last
1269
- last_developer = Developer.send(:with_scope, :find => { :order => 'developers.salary ASC' }) do
1270
- Developer.find(:last)
1271
- end
1272
- assert_equal last_developer, Developer.find(:all, :order => 'developers.salary ASC').last
1273
- end
1274
-
1275
- def test_abstract_class
1276
- assert !ActiveRecord::Base.abstract_class?
1277
- assert LoosePerson.abstract_class?
1278
- assert !LooseDescendant.abstract_class?
1279
- end
1280
-
1281
- def test_base_class
1282
- assert_equal LoosePerson, LoosePerson.base_class
1283
- assert_equal LooseDescendant, LooseDescendant.base_class
1284
- assert_equal TightPerson, TightPerson.base_class
1285
- assert_equal TightPerson, TightDescendant.base_class
1286
-
1287
- assert_equal Post, Post.base_class
1288
- assert_equal Post, SpecialPost.base_class
1289
- assert_equal Post, StiPost.base_class
1290
- assert_equal SubStiPost, SubStiPost.base_class
1291
- end
1292
-
1293
- def test_descends_from_active_record
1294
- # Tries to call Object.abstract_class?
1295
- assert_raise(NoMethodError) do
1296
- ActiveRecord::Base.descends_from_active_record?
1297
- end
1298
-
1299
- # Abstract subclass of AR::Base.
1300
- assert LoosePerson.descends_from_active_record?
1301
-
1302
- # Concrete subclass of an abstract class.
1303
- assert LooseDescendant.descends_from_active_record?
1304
-
1305
- # Concrete subclass of AR::Base.
1306
- assert TightPerson.descends_from_active_record?
1307
-
1308
- # Concrete subclass of a concrete class but has no type column.
1309
- assert TightDescendant.descends_from_active_record?
1310
-
1311
- # Concrete subclass of AR::Base.
1312
- assert Post.descends_from_active_record?
1313
-
1314
- # Abstract subclass of a concrete class which has a type column.
1315
- # This is pathological, as you'll never have Sub < Abstract < Concrete.
1316
- assert !StiPost.descends_from_active_record?
1317
-
1318
- # Concrete subclasses an abstract class which has a type column.
1319
- assert !SubStiPost.descends_from_active_record?
1320
- end
1321
-
1322
- def test_find_on_abstract_base_class_doesnt_use_type_condition
1323
- old_class = LooseDescendant
1324
- Object.send :remove_const, :LooseDescendant
1325
-
1326
- descendant = old_class.create! :first_name => 'bob'
1327
- assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}"
1328
- ensure
1329
- unless Object.const_defined?(:LooseDescendant)
1330
- Object.const_set :LooseDescendant, old_class
1331
- end
1332
- end
1333
-
1334
- def test_assert_queries
1335
- query = lambda { ActiveRecord::Base.connection.execute 'select count(*) from developers' }
1336
- assert_queries(2) { 2.times { query.call } }
1337
- assert_queries 1, &query
1338
- assert_no_queries { assert true }
1339
- end
1340
-
1341
- def test_to_param_should_return_string
1342
- assert_kind_of String, Client.find(:first).to_param
1343
- end
1344
-
1345
- def test_inspect_class
1346
- assert_equal 'ActiveRecord::Base', ActiveRecord::Base.inspect
1347
- assert_equal 'LoosePerson(abstract)', LoosePerson.inspect
1348
- assert_match(/^Topic\(id: integer, title: string/, Topic.inspect)
1349
- end
1350
-
1351
- def test_inspect_instance
1352
- topic = topics(:first)
1353
- 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, parent_title: nil, type: nil, group: nil>), topic.inspect
1354
- end
1355
-
1356
- def test_inspect_new_instance
1357
- assert_match(/Topic id: nil/, Topic.new.inspect)
1358
- end
1359
-
1360
- def test_inspect_limited_select_instance
1361
- assert_equal %(#<Topic id: 1>), Topic.find(:first, :select => 'id', :conditions => 'id = 1').inspect
1362
- assert_equal %(#<Topic id: 1, title: "The First Topic">), Topic.find(:first, :select => 'id, title', :conditions => 'id = 1').inspect
1363
- end
1364
-
1365
- def test_inspect_class_without_table
1366
- assert_equal "NonExistentTable(Table doesn't exist)", NonExistentTable.inspect
1367
- end
1368
-
1369
- def test_attribute_for_inspect
1370
- t = topics(:first)
1371
- t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
1372
-
1373
- assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on)
1374
- assert_equal '"The First Topic Now Has A Title With\nNewlines And M..."', t.attribute_for_inspect(:title)
1375
- end
1376
-
1377
- def test_becomes
1378
- assert_kind_of Reply, topics(:first).becomes(Reply)
1379
- assert_equal "The First Topic", topics(:first).becomes(Reply).title
1380
- end
1381
-
1382
- def test_silence_sets_log_level_to_error_in_block
1383
- original_logger = ActiveRecord::Base.logger
1384
- log = StringIO.new
1385
- ActiveRecord::Base.logger = Logger.new(log)
1386
- ActiveRecord::Base.logger.level = Logger::DEBUG
1387
- ActiveRecord::Base.silence do
1388
- ActiveRecord::Base.logger.warn "warn"
1389
- ActiveRecord::Base.logger.error "error"
1390
- end
1391
- assert_equal "error\n", log.string
1392
- ensure
1393
- ActiveRecord::Base.logger = original_logger
1394
- end
1395
-
1396
- def test_silence_sets_log_level_back_to_level_before_yield
1397
- original_logger = ActiveRecord::Base.logger
1398
- log = StringIO.new
1399
- ActiveRecord::Base.logger = Logger.new(log)
1400
- ActiveRecord::Base.logger.level = Logger::WARN
1401
- ActiveRecord::Base.silence do
1402
- end
1403
- assert_equal Logger::WARN, ActiveRecord::Base.logger.level
1404
- ensure
1405
- ActiveRecord::Base.logger = original_logger
1406
- end
1407
-
1408
- def test_benchmark_with_log_level
1409
- original_logger = ActiveRecord::Base.logger
1410
- log = StringIO.new
1411
- ActiveRecord::Base.logger = Logger.new(log)
1412
- ActiveRecord::Base.logger.level = Logger::WARN
1413
- ActiveRecord::Base.benchmark("Debug Topic Count", :level => :debug) { Topic.count }
1414
- ActiveRecord::Base.benchmark("Warn Topic Count", :level => :warn) { Topic.count }
1415
- ActiveRecord::Base.benchmark("Error Topic Count", :level => :error) { Topic.count }
1416
- assert_no_match(/Debug Topic Count/, log.string)
1417
- assert_match(/Warn Topic Count/, log.string)
1418
- assert_match(/Error Topic Count/, log.string)
1419
- ensure
1420
- ActiveRecord::Base.logger = original_logger
1421
- end
1422
-
1423
- def test_benchmark_with_use_silence
1424
- original_logger = ActiveRecord::Base.logger
1425
- log = StringIO.new
1426
- ActiveRecord::Base.logger = Logger.new(log)
1427
- ActiveRecord::Base.benchmark("Logging", :level => :debug, :silence => true) { ActiveRecord::Base.logger.debug "Loud" }
1428
- ActiveRecord::Base.benchmark("Logging", :level => :debug, :silence => false) { ActiveRecord::Base.logger.debug "Quiet" }
1429
- assert_no_match(/Loud/, log.string)
1430
- assert_match(/Quiet/, log.string)
1431
- ensure
1432
- ActiveRecord::Base.logger = original_logger
1433
- end
1434
-
1435
- def test_dup
1436
- assert !Minimalistic.new.freeze.dup.frozen?
1437
- end
1438
-
1439
- def test_compute_type_success
1440
- assert_equal Author, ActiveRecord::Base.send(:compute_type, 'Author')
1441
- end
1442
-
1443
- def test_compute_type_nonexistent_constant
1444
- assert_raises NameError do
1445
- ActiveRecord::Base.send :compute_type, 'NonexistentModel'
1446
- end
1447
- end
1448
-
1449
- def test_compute_type_no_method_error
1450
- ActiveSupport::Dependencies.stubs(:constantize).raises(NoMethodError)
1451
- assert_raises NoMethodError do
1452
- ActiveRecord::Base.send :compute_type, 'InvalidModel'
1453
- end
1454
- end
1455
-
1456
- def test_default_scope_is_reset
1457
- Object.const_set :UnloadablePost, Class.new(ActiveRecord::Base)
1458
- UnloadablePost.table_name = 'posts'
1459
- UnloadablePost.class_eval do
1460
- default_scope order('posts.comments_count ASC')
1461
- end
1462
- UnloadablePost.scoped_methods # make Thread.current[:UnloadablePost_scoped_methods] not nil
1463
-
1464
- UnloadablePost.unloadable
1465
- assert_not_nil Thread.current[:UnloadablePost_scoped_methods]
1466
- ActiveSupport::Dependencies.remove_unloadable_constants!
1467
- assert_nil Thread.current[:UnloadablePost_scoped_methods]
1468
- ensure
1469
- Object.class_eval{ remove_const :UnloadablePost } if defined?(UnloadablePost)
1470
- end
1471
-
1472
- protected
1473
- def with_env_tz(new_tz = 'US/Eastern')
1474
- old_tz, ENV['TZ'] = ENV['TZ'], new_tz
1475
- yield
1476
- ensure
1477
- old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
1478
- end
1479
-
1480
- def with_active_record_default_timezone(zone)
1481
- old_zone, ActiveRecord::Base.default_timezone = ActiveRecord::Base.default_timezone, zone
1482
- yield
1483
- ensure
1484
- ActiveRecord::Base.default_timezone = old_zone
1485
- end
1486
- end