ibm_db 2.5.6-x86-mingw32

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