ibm_db 1.1.1-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/CHANGES +155 -0
  2. data/LICENSE +18 -0
  3. data/MANIFEST +14 -0
  4. data/README +274 -0
  5. data/ext/Makefile.nt32 +181 -0
  6. data/ext/extconf.rb +58 -0
  7. data/ext/ibm_db.c +6553 -0
  8. data/ext/ruby_ibm_db.h +214 -0
  9. data/init.rb +42 -0
  10. data/lib/IBM_DB.rb +2 -0
  11. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +2218 -0
  12. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -0
  13. data/lib/mswin32/ibm_db.so +0 -0
  14. data/test/cases/adapter_test.rb +180 -0
  15. data/test/cases/associations/cascaded_eager_loading_test.rb +133 -0
  16. data/test/cases/associations/eager_test.rb +842 -0
  17. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +874 -0
  18. data/test/cases/associations/has_many_through_associations_test.rb +281 -0
  19. data/test/cases/associations/join_model_test.rb +801 -0
  20. data/test/cases/attribute_methods_test.rb +312 -0
  21. data/test/cases/base_test.rb +2114 -0
  22. data/test/cases/calculations_test.rb +346 -0
  23. data/test/cases/finder_test.rb +1092 -0
  24. data/test/cases/fixtures_test.rb +660 -0
  25. data/test/cases/migration_test.rb +1618 -0
  26. data/test/cases/schema_dumper_test.rb +197 -0
  27. data/test/cases/validations_test.rb +1604 -0
  28. data/test/connections/native_ibm_db/connection.rb +40 -0
  29. data/test/ibm_db_test.rb +25 -0
  30. data/test/models/warehouse_thing.rb +5 -0
  31. data/test/schema/i5/ibm_db_specific_schema.rb +134 -0
  32. data/test/schema/ids/ibm_db_specific_schema.rb +137 -0
  33. data/test/schema/luw/ibm_db_specific_schema.rb +134 -0
  34. data/test/schema/schema.rb +499 -0
  35. data/test/schema/zOS/ibm_db_specific_schema.rb +205 -0
  36. metadata +115 -0
@@ -0,0 +1,874 @@
1
+ require "cases/helper"
2
+ require 'models/developer'
3
+ require 'models/project'
4
+ require 'models/company'
5
+ require 'models/topic'
6
+ require 'models/reply'
7
+ require 'models/computer'
8
+ require 'models/customer'
9
+ require 'models/order'
10
+ require 'models/categorization'
11
+ require 'models/category'
12
+ require 'models/post'
13
+ require 'models/author'
14
+ require 'models/comment'
15
+ require 'models/tag'
16
+ require 'models/tagging'
17
+ require 'models/person'
18
+ require 'models/reader'
19
+ require 'models/parrot'
20
+ require 'models/pirate'
21
+ require 'models/treasure'
22
+ require 'models/price_estimate'
23
+ require 'models/club'
24
+ require 'models/member'
25
+ require 'models/membership'
26
+ require 'models/sponsor'
27
+
28
+ class ProjectWithAfterCreateHook < ActiveRecord::Base
29
+ set_table_name 'projects'
30
+ has_and_belongs_to_many :developers,
31
+ :class_name => "DeveloperForProjectWithAfterCreateHook",
32
+ :join_table => "developers_projects",
33
+ :foreign_key => "project_id",
34
+ :association_foreign_key => "developer_id"
35
+
36
+ after_create :add_david
37
+
38
+ def add_david
39
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
40
+ david.projects << self
41
+ end
42
+ end
43
+
44
+ class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
45
+ set_table_name 'developers'
46
+ has_and_belongs_to_many :projects,
47
+ :class_name => "ProjectWithAfterCreateHook",
48
+ :join_table => "developers_projects",
49
+ :association_foreign_key => "project_id",
50
+ :foreign_key => "developer_id"
51
+ end
52
+
53
+ class ProjectWithSymbolsForKeys < ActiveRecord::Base
54
+ set_table_name 'projects'
55
+ has_and_belongs_to_many :developers,
56
+ :class_name => "DeveloperWithSymbolsForKeys",
57
+ :join_table => :developers_projects,
58
+ :foreign_key => :project_id,
59
+ :association_foreign_key => "developer_id"
60
+ end
61
+
62
+ class DeveloperWithSymbolsForKeys < ActiveRecord::Base
63
+ set_table_name 'developers'
64
+ has_and_belongs_to_many :projects,
65
+ :class_name => "ProjectWithSymbolsForKeys",
66
+ :join_table => :developers_projects,
67
+ :association_foreign_key => :project_id,
68
+ :foreign_key => "developer_id"
69
+ end
70
+
71
+ class DeveloperWithCounterSQL < ActiveRecord::Base
72
+ set_table_name 'developers'
73
+ has_and_belongs_to_many :projects,
74
+ :class_name => "DeveloperWithCounterSQL",
75
+ :join_table => "developers_projects",
76
+ :association_foreign_key => "project_id",
77
+ :foreign_key => "developer_id",
78
+ :counter_sql => 'SELECT COUNT(*) AS count_all FROM projects INNER JOIN developers_projects ON projects.id = developers_projects.project_id WHERE developers_projects.developer_id =#{id}'
79
+ end
80
+
81
+ if current_adapter?(:IBM_DBAdapter)
82
+ class Novel < ActiveRecord::Base
83
+ has_and_belongs_to_many :writers
84
+ end
85
+
86
+ class Writer < ActiveRecord::Base
87
+ has_and_belongs_to_many :novels
88
+ end
89
+
90
+ class NovelsWriter < ActiveRecord::Base
91
+ belongs_to :writers
92
+ belongs_to :novels
93
+ end
94
+ end
95
+
96
+ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
97
+ fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
98
+ :parrots, :pirates, :treasures, :price_estimates, :tags, :taggings
99
+
100
+ def test_has_and_belongs_to_many
101
+ david = Developer.find(1)
102
+
103
+ assert !david.projects.empty?
104
+ assert_equal 2, david.projects.size
105
+
106
+ active_record = Project.find(1)
107
+ assert !active_record.developers.empty?
108
+ assert_equal 3, active_record.developers.size
109
+ assert active_record.developers.include?(david)
110
+ end
111
+
112
+ def test_triple_equality
113
+ assert !(Array === Developer.find(1).projects)
114
+ assert Developer.find(1).projects === Array
115
+ end
116
+
117
+ def test_adding_single
118
+ jamis = Developer.find(2)
119
+ jamis.projects.reload # causing the collection to load
120
+ action_controller = Project.find(2)
121
+ assert_equal 1, jamis.projects.size
122
+ assert_equal 1, action_controller.developers.size
123
+
124
+ jamis.projects << action_controller
125
+
126
+ assert_equal 2, jamis.projects.size
127
+ assert_equal 2, jamis.projects(true).size
128
+ assert_equal 2, action_controller.developers(true).size
129
+ end
130
+
131
+ def test_adding_type_mismatch
132
+ jamis = Developer.find(2)
133
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
134
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
135
+ end
136
+
137
+ def test_adding_from_the_project
138
+ jamis = Developer.find(2)
139
+ action_controller = Project.find(2)
140
+ action_controller.developers.reload
141
+ assert_equal 1, jamis.projects.size
142
+ assert_equal 1, action_controller.developers.size
143
+
144
+ action_controller.developers << jamis
145
+
146
+ assert_equal 2, jamis.projects(true).size
147
+ assert_equal 2, action_controller.developers.size
148
+ assert_equal 2, action_controller.developers(true).size
149
+ end
150
+
151
+ def test_adding_from_the_project_fixed_timestamp
152
+ jamis = Developer.find(2)
153
+ action_controller = Project.find(2)
154
+ action_controller.developers.reload
155
+ assert_equal 1, jamis.projects.size
156
+ assert_equal 1, action_controller.developers.size
157
+ updated_at = jamis.updated_at
158
+
159
+ action_controller.developers << jamis
160
+
161
+ assert_equal updated_at, jamis.updated_at
162
+ assert_equal 2, jamis.projects(true).size
163
+ assert_equal 2, action_controller.developers.size
164
+ assert_equal 2, action_controller.developers(true).size
165
+ end
166
+
167
+ def test_adding_multiple
168
+ aredridel = Developer.new("name" => "Aredridel")
169
+ aredridel.save
170
+ aredridel.projects.reload
171
+ aredridel.projects.push(Project.find(1), Project.find(2))
172
+ assert_equal 2, aredridel.projects.size
173
+ assert_equal 2, aredridel.projects(true).size
174
+ end
175
+
176
+ def test_adding_a_collection
177
+ aredridel = Developer.new("name" => "Aredridel")
178
+ aredridel.save
179
+ aredridel.projects.reload
180
+ aredridel.projects.concat([Project.find(1), Project.find(2)])
181
+ assert_equal 2, aredridel.projects.size
182
+ assert_equal 2, aredridel.projects(true).size
183
+ end
184
+
185
+ def test_adding_uses_default_values_on_join_table
186
+ ac = projects(:action_controller)
187
+ assert !developers(:jamis).projects.include?(ac)
188
+ developers(:jamis).projects << ac
189
+
190
+ assert developers(:jamis, :reload).projects.include?(ac)
191
+ project = developers(:jamis).projects.detect { |p| p == ac }
192
+ assert_equal 1, project.access_level.to_i
193
+ end
194
+
195
+ def test_habtm_attribute_access_and_respond_to
196
+ project = developers(:jamis).projects[0]
197
+ assert project.has_attribute?("name")
198
+ assert project.has_attribute?("joined_on")
199
+ assert project.has_attribute?("access_level")
200
+ assert project.respond_to?("name")
201
+ assert project.respond_to?("name=")
202
+ assert project.respond_to?("name?")
203
+ assert project.respond_to?("joined_on")
204
+ # given that the 'join attribute' won't be persisted, I don't
205
+ # think we should define the mutators
206
+ #assert project.respond_to?("joined_on=")
207
+ assert project.respond_to?("joined_on?")
208
+ assert project.respond_to?("access_level")
209
+ #assert project.respond_to?("access_level=")
210
+ assert project.respond_to?("access_level?")
211
+ end
212
+
213
+ def test_habtm_adding_before_save
214
+ no_of_devels = Developer.count
215
+ no_of_projects = Project.count
216
+ aredridel = Developer.new("name" => "Aredridel")
217
+ aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
218
+ assert aredridel.new_record?
219
+ assert p.new_record?
220
+ assert aredridel.save
221
+ assert !aredridel.new_record?
222
+ assert_equal no_of_devels+1, Developer.count
223
+ assert_equal no_of_projects+1, Project.count
224
+ assert_equal 2, aredridel.projects.size
225
+ assert_equal 2, aredridel.projects(true).size
226
+ end
227
+
228
+ def test_habtm_saving_multiple_relationships
229
+ new_project = Project.new("name" => "Grimetime")
230
+ amount_of_developers = 4
231
+ developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
232
+
233
+ new_project.developer_ids = [developers[0].id, developers[1].id]
234
+ new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
235
+ assert new_project.save
236
+
237
+ new_project.reload
238
+ assert_equal amount_of_developers, new_project.developers.size
239
+ assert_equal developers, new_project.developers
240
+ end
241
+
242
+ def test_habtm_unique_order_preserved
243
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
244
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
245
+ end
246
+
247
+ def test_build
248
+ devel = Developer.find(1)
249
+ proj = assert_no_queries { devel.projects.build("name" => "Projekt") }
250
+ assert !devel.projects.loaded?
251
+
252
+ assert_equal devel.projects.last, proj
253
+ assert devel.projects.loaded?
254
+
255
+ assert proj.new_record?
256
+ devel.save
257
+ assert !proj.new_record?
258
+ assert_equal devel.projects.last, proj
259
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
260
+ end
261
+
262
+ def test_build_by_new_record
263
+ devel = Developer.new(:name => "Marcel", :salary => 75000)
264
+ proj1 = devel.projects.build(:name => "Make bed")
265
+ proj2 = devel.projects.build(:name => "Lie in it")
266
+ assert_equal devel.projects.last, proj2
267
+ assert proj2.new_record?
268
+ devel.save
269
+ assert !devel.new_record?
270
+ assert !proj2.new_record?
271
+ assert_equal devel.projects.last, proj2
272
+ assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
273
+ end
274
+
275
+ def test_create
276
+ devel = Developer.find(1)
277
+ proj = devel.projects.create("name" => "Projekt")
278
+ assert !devel.projects.loaded?
279
+
280
+ assert_equal devel.projects.last, proj
281
+ assert !devel.projects.loaded?
282
+
283
+ assert !proj.new_record?
284
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
285
+ end
286
+
287
+ if current_adapter?(:IBM_DBAdapter)
288
+ def test_lob_handling
289
+ assert_nothing_raised do
290
+ Novel.connection.create_table 'novels' do |t|
291
+ t.text :story
292
+ t.string :title
293
+ end
294
+ Writer.connection.create_table 'writers' do |t|
295
+ t.string :name
296
+ end
297
+ NovelsWriter.connection.create_table 'novels_writers' do |t|
298
+ t.belongs_to :novels
299
+ t.belongs_to :writers
300
+ end
301
+ end
302
+
303
+ w = Writer.new :name => 'Praveen'
304
+ w.save!
305
+
306
+ novel_story = "This is a short and sweet story"
307
+
308
+ novel = Novel.new :story => novel_story,:title => "Cool isn't it"
309
+ novel.writers << w
310
+ novel.save!
311
+
312
+ assert_equal novel_story,Novel.find(novel.id).story
313
+ ensure
314
+ Novel.connection.drop_table 'novels' rescue nil
315
+ Writer.connection.drop_table 'writers' rescue nil
316
+ NovelsWriter.connection.drop_table 'novels_writers' rescue nil
317
+ end
318
+ end
319
+
320
+ def test_create_by_new_record
321
+ devel = Developer.new(:name => "Marcel", :salary => 75000)
322
+ proj1 = devel.projects.build(:name => "Make bed")
323
+ proj2 = devel.projects.build(:name => "Lie in it")
324
+ assert_equal devel.projects.last, proj2
325
+ assert proj2.new_record?
326
+ devel.save
327
+ assert !devel.new_record?
328
+ assert !proj2.new_record?
329
+ assert_equal devel.projects.last, proj2
330
+ assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
331
+ end
332
+
333
+ def test_creation_respects_hash_condition
334
+ post = categories(:general).post_with_conditions.build(:body => '')
335
+
336
+ assert post.save
337
+ assert_equal 'Yet Another Testing Title', post.title
338
+
339
+ another_post = categories(:general).post_with_conditions.create(:body => '')
340
+
341
+ assert !another_post.new_record?
342
+ assert_equal 'Yet Another Testing Title', another_post.title
343
+ end
344
+
345
+ def test_uniq_after_the_fact
346
+ dev = developers(:jamis)
347
+ dev.projects << projects(:active_record)
348
+ dev.projects << projects(:active_record)
349
+
350
+ assert_equal 3, dev.projects.size
351
+ assert_equal 1, dev.projects.uniq.size
352
+ end
353
+
354
+ def test_uniq_before_the_fact
355
+ projects(:active_record).developers << developers(:jamis)
356
+ projects(:active_record).developers << developers(:david)
357
+ assert_equal 3, projects(:active_record, :reload).developers.size
358
+ end
359
+
360
+ def test_uniq_option_prevents_duplicate_push
361
+ project = projects(:active_record)
362
+ project.developers << developers(:jamis)
363
+ project.developers << developers(:david)
364
+ assert_equal 3, project.developers.size
365
+
366
+ project.developers << developers(:david)
367
+ project.developers << developers(:jamis)
368
+ assert_equal 3, project.developers.size
369
+ end
370
+
371
+ def test_deleting
372
+ david = Developer.find(1)
373
+ active_record = Project.find(1)
374
+ david.projects.reload
375
+ assert_equal 2, david.projects.size
376
+ assert_equal 3, active_record.developers.size
377
+
378
+ david.projects.delete(active_record)
379
+
380
+ assert_equal 1, david.projects.size
381
+ assert_equal 1, david.projects(true).size
382
+ assert_equal 2, active_record.developers(true).size
383
+ end
384
+
385
+ def test_deleting_array
386
+ david = Developer.find(1)
387
+ david.projects.reload
388
+ david.projects.delete(Project.find(:all))
389
+ assert_equal 0, david.projects.size
390
+ assert_equal 0, david.projects(true).size
391
+ end
392
+
393
+ def test_deleting_with_sql
394
+ david = Developer.find(1)
395
+ active_record = Project.find(1)
396
+ active_record.developers.reload
397
+ assert_equal 3, active_record.developers_by_sql.size
398
+
399
+ active_record.developers_by_sql.delete(david)
400
+ assert_equal 2, active_record.developers_by_sql(true).size
401
+ end
402
+
403
+ def test_deleting_array_with_sql
404
+ active_record = Project.find(1)
405
+ active_record.developers.reload
406
+ assert_equal 3, active_record.developers_by_sql.size
407
+
408
+ active_record.developers_by_sql.delete(Developer.find(:all))
409
+ assert_equal 0, active_record.developers_by_sql(true).size
410
+ end
411
+
412
+ def test_deleting_all
413
+ david = Developer.find(1)
414
+ david.projects.reload
415
+ david.projects.clear
416
+ assert_equal 0, david.projects.size
417
+ assert_equal 0, david.projects(true).size
418
+ end
419
+
420
+ def test_removing_associations_on_destroy
421
+ david = DeveloperWithBeforeDestroyRaise.find(1)
422
+ assert !david.projects.empty?
423
+ assert_nothing_raised { david.destroy }
424
+ assert david.projects.empty?
425
+ assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
426
+ end
427
+
428
+ def test_additional_columns_from_join_table
429
+ assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on.to_date
430
+ end
431
+
432
+ def test_destroying
433
+ david = Developer.find(1)
434
+ active_record = Project.find(1)
435
+ david.projects.reload
436
+ assert_equal 2, david.projects.size
437
+ assert_equal 3, active_record.developers.size
438
+
439
+ assert_difference "Project.count", -1 do
440
+ david.projects.destroy(active_record)
441
+ end
442
+
443
+ assert_equal 1, david.reload.projects.size
444
+ assert_equal 1, david.projects(true).size
445
+ end
446
+
447
+ def test_destroying_array
448
+ david = Developer.find(1)
449
+ david.projects.reload
450
+
451
+ assert_difference "Project.count", -Project.count do
452
+ david.projects.destroy(Project.find(:all))
453
+ end
454
+
455
+ assert_equal 0, david.reload.projects.size
456
+ assert_equal 0, david.projects(true).size
457
+ end
458
+
459
+ def test_destroy_all
460
+ david = Developer.find(1)
461
+ david.projects.reload
462
+ assert !david.projects.empty?
463
+ david.projects.destroy_all
464
+ assert david.projects.empty?
465
+ assert david.projects(true).empty?
466
+ end
467
+
468
+ def test_deprecated_push_with_attributes_was_removed
469
+ jamis = developers(:jamis)
470
+ assert_raise(NoMethodError) do
471
+ jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
472
+ end
473
+ end
474
+
475
+ def test_associations_with_conditions
476
+ assert_equal 3, projects(:active_record).developers.size
477
+ assert_equal 1, projects(:active_record).developers_named_david.size
478
+ assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
479
+
480
+ assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
481
+ assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
482
+ assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
483
+
484
+ projects(:active_record).developers_named_david.clear
485
+ assert_equal 2, projects(:active_record, :reload).developers.size
486
+ end
487
+
488
+ def test_find_in_association
489
+ # Using sql
490
+ assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
491
+
492
+ # Using ruby
493
+ active_record = projects(:active_record)
494
+ active_record.developers.reload
495
+ assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
496
+ end
497
+
498
+ def test_include_uses_array_include_after_loaded
499
+ project = projects(:active_record)
500
+ project.developers.class # force load target
501
+
502
+ developer = project.developers.first
503
+
504
+ assert_no_queries do
505
+ assert project.developers.loaded?
506
+ assert project.developers.include?(developer)
507
+ end
508
+ end
509
+
510
+ def test_include_checks_if_record_exists_if_target_not_loaded
511
+ project = projects(:active_record)
512
+ developer = project.developers.first
513
+
514
+ project.reload
515
+ assert ! project.developers.loaded?
516
+ assert_queries(1) do
517
+ assert project.developers.include?(developer)
518
+ end
519
+ assert ! project.developers.loaded?
520
+ end
521
+
522
+ def test_include_returns_false_for_non_matching_record_to_verify_scoping
523
+ project = projects(:active_record)
524
+ developer = Developer.create :name => "Bryan", :salary => 50_000
525
+
526
+ assert ! project.developers.loaded?
527
+ assert ! project.developers.include?(developer)
528
+ end
529
+
530
+ def test_find_in_association_with_custom_finder_sql
531
+ assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id), "SQL find"
532
+
533
+ active_record = projects(:active_record)
534
+ active_record.developers_with_finder_sql.reload
535
+ assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find"
536
+ end
537
+
538
+ def test_find_in_association_with_custom_finder_sql_and_multiple_interpolations
539
+ # interpolate once:
540
+ assert_equal [developers(:david), developers(:jamis), developers(:poor_jamis)], projects(:active_record).developers_with_finder_sql, "first interpolation"
541
+ # interpolate again, for a different project id
542
+ assert_equal [developers(:david)], projects(:action_controller).developers_with_finder_sql, "second interpolation"
543
+ end
544
+
545
+ def test_find_in_association_with_custom_finder_sql_and_string_id
546
+ assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find"
547
+ end
548
+
549
+ def test_find_with_merged_options
550
+ assert_equal 1, projects(:active_record).limited_developers.size
551
+ assert_equal 1, projects(:active_record).limited_developers.find(:all).size
552
+ assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size
553
+ end
554
+
555
+ def test_dynamic_find_should_respect_association_order
556
+ # Developers are ordered 'name DESC, id DESC'
557
+ low_id_jamis = developers(:jamis)
558
+ middle_id_jamis = developers(:poor_jamis)
559
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
560
+
561
+ assert_equal high_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'")
562
+ assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
563
+ end
564
+
565
+ def test_dynamic_find_order_should_override_association_order
566
+ # Developers are ordered 'name DESC, id DESC'
567
+ low_id_jamis = developers(:jamis)
568
+ middle_id_jamis = developers(:poor_jamis)
569
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
570
+
571
+ assert_equal low_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'", :order => 'id')
572
+ assert_equal low_id_jamis, projects(:active_record).developers.find_by_name('Jamis', :order => 'id')
573
+ end
574
+
575
+ def test_dynamic_find_all_should_respect_association_order
576
+ # Developers are ordered 'name DESC, id DESC'
577
+ low_id_jamis = developers(:jamis)
578
+ middle_id_jamis = developers(:poor_jamis)
579
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
580
+
581
+ assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'")
582
+ assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis')
583
+ end
584
+
585
+ def test_dynamic_find_all_order_should_override_association_order
586
+ # Developers are ordered 'name DESC, id DESC'
587
+ low_id_jamis = developers(:jamis)
588
+ middle_id_jamis = developers(:poor_jamis)
589
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
590
+
591
+ assert_equal [low_id_jamis, middle_id_jamis, high_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'", :order => 'id')
592
+ assert_equal [low_id_jamis, middle_id_jamis, high_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis', :order => 'id')
593
+ end
594
+
595
+ def test_dynamic_find_all_should_respect_association_limit
596
+ assert_equal 1, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'").length
597
+ assert_equal 1, projects(:active_record).limited_developers.find_all_by_name('Jamis').length
598
+ end
599
+
600
+ def test_dynamic_find_all_order_should_override_association_limit
601
+ assert_equal 2, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'", :limit => 9_000).length
602
+ assert_equal 2, projects(:active_record).limited_developers.find_all_by_name('Jamis', :limit => 9_000).length
603
+ end
604
+
605
+ def test_dynamic_find_all_should_respect_readonly_access
606
+ projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
607
+ projects(:active_record).readonly_developers.each { |d| d.readonly? }
608
+ end
609
+
610
+ def test_new_with_values_in_collection
611
+ jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
612
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
613
+ project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
614
+ project.developers << jamis
615
+ project.save!
616
+ project.reload
617
+
618
+ assert project.developers.include?(jamis)
619
+ assert project.developers.include?(david)
620
+ end
621
+
622
+ def test_find_in_association_with_options
623
+ developers = projects(:active_record).developers.find(:all)
624
+ assert_equal 3, developers.size
625
+
626
+ assert_equal developers(:poor_jamis), projects(:active_record).developers.find(:first, :conditions => "salary < 10000")
627
+ assert_equal developers(:jamis), projects(:active_record).developers.find(:first, :order => "salary DESC")
628
+ end
629
+
630
+ def test_replace_with_less
631
+ david = developers(:david)
632
+ david.projects = [projects(:action_controller)]
633
+ assert david.save
634
+ assert_equal 1, david.projects.length
635
+ end
636
+
637
+ def test_replace_with_new
638
+ david = developers(:david)
639
+ david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
640
+ david.save
641
+ assert_equal 2, david.projects.length
642
+ assert !david.projects.include?(projects(:active_record))
643
+ end
644
+
645
+ def test_replace_on_new_object
646
+ new_developer = Developer.new("name" => "Matz")
647
+ new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
648
+ new_developer.save
649
+ assert_equal 2, new_developer.projects.length
650
+ end
651
+
652
+ def test_consider_type
653
+ developer = Developer.find(:first)
654
+ special_project = SpecialProject.create("name" => "Special Project")
655
+
656
+ other_project = developer.projects.first
657
+ developer.special_projects << special_project
658
+ developer.reload
659
+
660
+ assert developer.projects.include?(special_project)
661
+ assert developer.special_projects.include?(special_project)
662
+ assert !developer.special_projects.include?(other_project)
663
+ end
664
+
665
+ def test_update_attributes_after_push_without_duplicate_join_table_rows
666
+ developer = Developer.new("name" => "Kano")
667
+ project = SpecialProject.create("name" => "Special Project")
668
+ assert developer.save
669
+ developer.projects << project
670
+ developer.update_attribute("name", "Bruza")
671
+ assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
672
+ SELECT count(*) FROM developers_projects
673
+ WHERE project_id = #{project.id}
674
+ AND developer_id = #{developer.id}
675
+ end_sql
676
+ end
677
+
678
+ def test_updating_attributes_on_non_rich_associations
679
+ welcome = categories(:technology).posts.first
680
+ welcome.title = "Something else"
681
+ assert welcome.save!
682
+ end
683
+
684
+ def test_habtm_respects_select
685
+ categories(:technology).select_testing_posts(true).each do |o|
686
+ assert_respond_to o, :correctness_marker
687
+ end
688
+ assert_respond_to categories(:technology).select_testing_posts.find(:first), :correctness_marker
689
+ end
690
+
691
+ def test_updating_attributes_on_rich_associations
692
+ david = projects(:action_controller).developers.first
693
+ david.name = "DHH"
694
+ assert_raise(ActiveRecord::ReadOnlyRecord) { david.save! }
695
+ end
696
+
697
+ def test_updating_attributes_on_rich_associations_with_limited_find_from_reflection
698
+ david = projects(:action_controller).selected_developers.first
699
+ david.name = "DHH"
700
+ assert_nothing_raised { david.save! }
701
+ end
702
+
703
+
704
+ def test_updating_attributes_on_rich_associations_with_limited_find
705
+ david = projects(:action_controller).developers.find(:all, :select => "developers.*").first
706
+ david.name = "DHH"
707
+ assert david.save!
708
+ end
709
+
710
+ def test_join_table_alias
711
+ assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
712
+ end
713
+
714
+ def test_join_with_group
715
+ group = Developer.columns.inject([]) do |g, c|
716
+ g << "developers.#{c.name}"
717
+ g << "developers_projects_2.#{c.name}"
718
+ end
719
+ Project.columns.each { |c| group << "projects.#{c.name}" }
720
+
721
+ assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
722
+ end
723
+
724
+ def test_find_grouped
725
+ all_posts_from_category1 = Post.find(:all, :conditions => "category_id = 1", :joins => :categories)
726
+ grouped_posts_of_category1 = Post.find(:all, :conditions => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories)
727
+ assert_equal 4, all_posts_from_category1.size
728
+ assert_equal 1, grouped_posts_of_category1.size
729
+ end
730
+
731
+ def test_find_scoped_grouped
732
+ assert_equal 4, categories(:general).posts_gruoped_by_title.size
733
+ assert_equal 1, categories(:technology).posts_gruoped_by_title.size
734
+ end
735
+
736
+ def test_find_scoped_grouped_having
737
+ assert_equal 2, projects(:active_record).well_payed_salary_groups.size
738
+ assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
739
+ end
740
+
741
+ def test_get_ids
742
+ assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
743
+ assert_equal [projects(:active_record).id], developers(:jamis).project_ids
744
+ end
745
+
746
+ def test_get_ids_for_loaded_associations
747
+ developer = developers(:david)
748
+ developer.projects(true)
749
+ assert_queries(0) do
750
+ developer.project_ids
751
+ developer.project_ids
752
+ end
753
+ end
754
+
755
+ def test_get_ids_for_unloaded_associations_does_not_load_them
756
+ developer = developers(:david)
757
+ assert !developer.projects.loaded?
758
+ assert_equal projects(:active_record, :action_controller).map(&:id).sort, developer.project_ids.sort
759
+ assert !developer.projects.loaded?
760
+ end
761
+
762
+ def test_assign_ids
763
+ developer = Developer.new("name" => "Joe")
764
+ developer.project_ids = projects(:active_record, :action_controller).map(&:id)
765
+ developer.save
766
+ developer.reload
767
+ assert_equal 2, developer.projects.length
768
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
769
+ end
770
+
771
+ def test_assign_ids_ignoring_blanks
772
+ developer = Developer.new("name" => "Joe")
773
+ developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
774
+ developer.save
775
+ developer.reload
776
+ assert_equal 2, developer.projects.length
777
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
778
+ end
779
+
780
+ unless current_adapter?(:IBM_DBAdapter)
781
+ def test_select_limited_ids_list
782
+ # Set timestamps
783
+ Developer.transaction do
784
+ Developer.find(:all, :order => 'id').each_with_index do |record, i|
785
+ record.update_attributes(:created_at => 5.years.ago + (i * 5.minutes))
786
+ end
787
+ end
788
+
789
+ join_base = ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase.new(Project)
790
+ join_dep = ActiveRecord::Associations::ClassMethods::JoinDependency.new(join_base, :developers, nil)
791
+ projects = Project.send(:select_limited_ids_list, {:order => 'developers.created_at'}, join_dep)
792
+ assert !projects.include?("'"), projects
793
+ assert_equal %w(1 2), projects.scan(/\d/).sort
794
+ end
795
+ end
796
+
797
+ def test_scoped_find_on_through_association_doesnt_return_read_only_records
798
+ tag = Post.find(1).tags.find_by_name("General")
799
+
800
+ assert_nothing_raised do
801
+ tag.save!
802
+ end
803
+ end
804
+
805
+ def test_has_many_through_polymorphic_has_manys_works
806
+ assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
807
+ end
808
+
809
+ def test_symbols_as_keys
810
+ developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
811
+ project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
812
+ project.developers << developer
813
+ project.save!
814
+
815
+ assert_equal 1, project.developers.size
816
+ assert_equal 1, developer.projects.size
817
+ assert_equal developer, project.developers.find(:first)
818
+ assert_equal project, developer.projects.find(:first)
819
+ end
820
+
821
+ def test_self_referential_habtm_without_foreign_key_set_should_raise_exception
822
+ assert_raise(ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded) {
823
+ Member.class_eval do
824
+ has_and_belongs_to_many :friends, :class_name => "Member", :join_table => "member_friends"
825
+ end
826
+ }
827
+ end
828
+
829
+ unless current_adapter?(:IBM_DBAdapter) #refer SQL214n
830
+ def test_dynamic_find_should_respect_association_include
831
+ # SQL error in sort clause if :include is not included
832
+ # due to Unknown column 'authors.id'
833
+ assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
834
+ end
835
+ end
836
+
837
+ def test_counting_on_habtm_association_and_not_array
838
+ david = Developer.find(1)
839
+ # Extra parameter just to make sure we aren't falling back to
840
+ # Array#count in Ruby >=1.8.7, which would raise an ArgumentError
841
+ assert_nothing_raised { david.projects.count(:all, :conditions => '1=1') }
842
+ end
843
+
844
+ def test_count
845
+ david = Developer.find(1)
846
+ assert_equal 2, david.projects.count
847
+ end
848
+
849
+ def test_count_with_counter_sql
850
+ developer = DeveloperWithCounterSQL.create(:name => 'tekin')
851
+ developer.project_ids = [projects(:active_record).id]
852
+ developer.save
853
+ developer.reload
854
+ assert_equal 1, developer.projects.count
855
+ end
856
+
857
+ def test_association_proxy_transaction_method_starts_transaction_in_association_class
858
+ Post.expects(:transaction)
859
+ Category.find(:first).posts.transaction do
860
+ # nothing
861
+ end
862
+ end
863
+
864
+ def test_caching_of_columns
865
+ david = Developer.find(1)
866
+ # clear cache possibly created by other tests
867
+ david.projects.reset_column_information
868
+ assert_queries(0) { david.projects.columns; david.projects.columns }
869
+ # and again to verify that reset_column_information clears the cache correctly
870
+ david.projects.reset_column_information
871
+ assert_queries(0) { david.projects.columns; david.projects.columns }
872
+ end
873
+
874
+ end