ibm_db 1.1.1-mswin32

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 (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,281 @@
1
+ require "cases/helper"
2
+ require 'models/post'
3
+ require 'models/person'
4
+ require 'models/reference'
5
+ require 'models/job'
6
+ require 'models/reader'
7
+ require 'models/comment'
8
+ require 'models/tag'
9
+ require 'models/tagging'
10
+ require 'models/author'
11
+ require 'models/owner'
12
+ require 'models/pet'
13
+ require 'models/toy'
14
+
15
+ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
16
+ fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys
17
+
18
+ def test_associate_existing
19
+ assert_queries(2) { posts(:thinking);people(:david) }
20
+
21
+ posts(:thinking).people
22
+
23
+ assert_queries(1) do
24
+ posts(:thinking).people << people(:david)
25
+ end
26
+
27
+ assert_queries(1) do
28
+ assert posts(:thinking).people.include?(people(:david))
29
+ end
30
+
31
+ assert posts(:thinking).reload.people(true).include?(people(:david))
32
+ end
33
+
34
+ def test_associating_new
35
+ assert_queries(1) { posts(:thinking) }
36
+ new_person = nil # so block binding catches it
37
+
38
+ assert_queries(0) do
39
+ new_person = Person.new :first_name => 'bob'
40
+ end
41
+
42
+ # Associating new records always saves them
43
+ # Thus, 1 query for the new person record, 1 query for the new join table record
44
+ assert_queries(2) do
45
+ posts(:thinking).people << new_person
46
+ end
47
+
48
+ assert_queries(1) do
49
+ assert posts(:thinking).people.include?(new_person)
50
+ end
51
+
52
+ assert posts(:thinking).reload.people(true).include?(new_person)
53
+ end
54
+
55
+ def test_associate_new_by_building
56
+ assert_queries(1) { posts(:thinking) }
57
+
58
+ assert_queries(0) do
59
+ posts(:thinking).people.build(:first_name=>"Bob")
60
+ posts(:thinking).people.new(:first_name=>"Ted")
61
+ end
62
+
63
+ # Should only need to load the association once
64
+ assert_queries(1) do
65
+ assert posts(:thinking).people.collect(&:first_name).include?("Bob")
66
+ assert posts(:thinking).people.collect(&:first_name).include?("Ted")
67
+ end
68
+
69
+ # 2 queries for each new record (1 to save the record itself, 1 for the join model)
70
+ # * 2 new records = 4
71
+ # + 1 query to save the actual post = 5
72
+ assert_queries(5) do
73
+ posts(:thinking).body += '-changed'
74
+ posts(:thinking).save
75
+ end
76
+
77
+ assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Bob")
78
+ assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Ted")
79
+ end
80
+
81
+ def test_delete_association
82
+ assert_queries(2){posts(:welcome);people(:michael); }
83
+
84
+ assert_queries(1) do
85
+ posts(:welcome).people.delete(people(:michael))
86
+ end
87
+
88
+ assert_queries(1) do
89
+ assert posts(:welcome).people.empty?
90
+ end
91
+
92
+ assert posts(:welcome).reload.people(true).empty?
93
+ end
94
+
95
+ def test_destroy_association
96
+ assert_difference "Person.count", -1 do
97
+ posts(:welcome).people.destroy(people(:michael))
98
+ end
99
+
100
+ assert posts(:welcome).reload.people.empty?
101
+ assert posts(:welcome).people(true).empty?
102
+ end
103
+
104
+ def test_destroy_all
105
+ assert_difference "Person.count", -1 do
106
+ posts(:welcome).people.destroy_all
107
+ end
108
+
109
+ assert posts(:welcome).reload.people.empty?
110
+ assert posts(:welcome).people(true).empty?
111
+ end
112
+
113
+ def test_replace_association
114
+ assert_queries(4){posts(:welcome);people(:david);people(:michael); posts(:welcome).people(true)}
115
+
116
+ # 1 query to delete the existing reader (michael)
117
+ # 1 query to associate the new reader (david)
118
+ assert_queries(2) do
119
+ posts(:welcome).people = [people(:david)]
120
+ end
121
+
122
+ assert_queries(0){
123
+ assert posts(:welcome).people.include?(people(:david))
124
+ assert !posts(:welcome).people.include?(people(:michael))
125
+ }
126
+
127
+ assert posts(:welcome).reload.people(true).include?(people(:david))
128
+ assert !posts(:welcome).reload.people(true).include?(people(:michael))
129
+ end
130
+
131
+ def test_associate_with_create
132
+ assert_queries(1) { posts(:thinking) }
133
+
134
+ # 1 query for the new record, 1 for the join table record
135
+ # No need to update the actual collection yet!
136
+ assert_queries(2) do
137
+ posts(:thinking).people.create(:first_name=>"Jeb")
138
+ end
139
+
140
+ # *Now* we actually need the collection so it's loaded
141
+ assert_queries(1) do
142
+ assert posts(:thinking).people.collect(&:first_name).include?("Jeb")
143
+ end
144
+
145
+ assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Jeb")
146
+ end
147
+
148
+ def test_associate_with_create_and_no_options
149
+ peeps = posts(:thinking).people.count
150
+ posts(:thinking).people.create(:first_name => 'foo')
151
+ assert_equal peeps + 1, posts(:thinking).people.count
152
+ end
153
+
154
+ def test_associate_with_create_exclamation_and_no_options
155
+ peeps = posts(:thinking).people.count
156
+ posts(:thinking).people.create!(:first_name => 'foo')
157
+ assert_equal peeps + 1, posts(:thinking).people.count
158
+ end
159
+
160
+ def test_clear_associations
161
+ assert_queries(2) { posts(:welcome);posts(:welcome).people(true) }
162
+
163
+ assert_queries(1) do
164
+ posts(:welcome).people.clear
165
+ end
166
+
167
+ assert_queries(0) do
168
+ assert posts(:welcome).people.empty?
169
+ end
170
+
171
+ assert posts(:welcome).reload.people(true).empty?
172
+ end
173
+
174
+ def test_association_callback_ordering
175
+ Post.reset_log
176
+ log = Post.log
177
+ post = posts(:thinking)
178
+
179
+ post.people_with_callbacks << people(:michael)
180
+ assert_equal [
181
+ [:added, :before, "Michael"],
182
+ [:added, :after, "Michael"]
183
+ ], log.last(2)
184
+
185
+ post.people_with_callbacks.push(people(:david), Person.create!(:first_name => "Bob"), Person.new(:first_name => "Lary"))
186
+ assert_equal [
187
+ [:added, :before, "David"],
188
+ [:added, :after, "David"],
189
+ [:added, :before, "Bob"],
190
+ [:added, :after, "Bob"],
191
+ [:added, :before, "Lary"],
192
+ [:added, :after, "Lary"]
193
+ ],log.last(6)
194
+
195
+ post.people_with_callbacks.build(:first_name => "Ted")
196
+ assert_equal [
197
+ [:added, :before, "Ted"],
198
+ [:added, :after, "Ted"]
199
+ ], log.last(2)
200
+
201
+ post.people_with_callbacks.create(:first_name => "Sam")
202
+ assert_equal [
203
+ [:added, :before, "Sam"],
204
+ [:added, :after, "Sam"]
205
+ ], log.last(2)
206
+
207
+ post.people_with_callbacks = [people(:michael),people(:david), Person.new(:first_name => "Julian"), Person.create!(:first_name => "Roger")]
208
+ assert_equal (%w(Ted Bob Sam Lary) * 2).sort, log[-12..-5].collect(&:last).sort
209
+ assert_equal [
210
+ [:added, :before, "Julian"],
211
+ [:added, :after, "Julian"],
212
+ [:added, :before, "Roger"],
213
+ [:added, :after, "Roger"]
214
+ ], log.last(4)
215
+
216
+ post.people_with_callbacks.clear
217
+ assert_equal (%w(Michael David Julian Roger) * 2).sort, log.last(8).collect(&:last).sort
218
+ end
219
+
220
+ unless current_adapter?(:IBM_DBAdapter) #refer db2 ? SQL0214N
221
+ def test_dynamic_find_should_respect_association_include
222
+ # SQL error in sort clause if :include is not included
223
+ # due to Unknown column 'comments.id'
224
+ assert Person.find(1).posts_with_comments_sorted_by_comment_id.find_by_title('Welcome to the weblog')
225
+ end
226
+ end
227
+
228
+ def test_count_with_include_should_alias_join_table
229
+ assert_equal 2, people(:michael).posts.count(:include => :readers)
230
+ end
231
+
232
+ def test_inner_join_with_quoted_table_name
233
+ assert_equal 2, people(:michael).jobs.size
234
+ end
235
+
236
+ def test_get_ids
237
+ assert_equal [posts(:welcome).id, posts(:authorless).id].sort, people(:michael).post_ids.sort
238
+ end
239
+
240
+ def test_get_ids_for_loaded_associations
241
+ person = people(:michael)
242
+ person.posts(true)
243
+ assert_queries(0) do
244
+ person.post_ids
245
+ person.post_ids
246
+ end
247
+ end
248
+
249
+ def test_get_ids_for_unloaded_associations_does_not_load_them
250
+ person = people(:michael)
251
+ assert !person.posts.loaded?
252
+ assert_equal [posts(:welcome).id, posts(:authorless).id].sort, person.post_ids.sort
253
+ assert !person.posts.loaded?
254
+ end
255
+
256
+ def test_association_proxy_transaction_method_starts_transaction_in_association_class
257
+ Tag.expects(:transaction)
258
+ Post.find(:first).tags.transaction do
259
+ # nothing
260
+ end
261
+ end
262
+
263
+ def test_has_many_association_through_a_belongs_to_association_where_the_association_doesnt_exist
264
+ author = authors(:mary)
265
+ post = Post.create!(:title => "TITLE", :body => "BODY")
266
+ assert_equal [], post.author_favorites
267
+ end
268
+
269
+ def test_has_many_association_through_a_belongs_to_association
270
+ author = authors(:mary)
271
+ post = Post.create!(:author => author, :title => "TITLE", :body => "BODY")
272
+ author.author_favorites.create(:favorite_author_id => 1)
273
+ author.author_favorites.create(:favorite_author_id => 2)
274
+ author.author_favorites.create(:favorite_author_id => 3)
275
+ assert_equal post.author.author_favorites, post.author_favorites
276
+ end
277
+
278
+ def test_has_many_association_through_a_has_many_association_with_nonstandard_primary_keys
279
+ assert_equal 1, owners(:blackbeard).toys.count
280
+ end
281
+ end
@@ -0,0 +1,801 @@
1
+ require "cases/helper"
2
+ require 'models/tag'
3
+ require 'models/tagging'
4
+ require 'models/post'
5
+ require 'models/item'
6
+ require 'models/comment'
7
+ require 'models/author'
8
+ require 'models/category'
9
+ require 'models/categorization'
10
+ require 'models/vertex'
11
+ require 'models/edge'
12
+ require 'models/book'
13
+ require 'models/citation'
14
+
15
+ class AssociationsJoinModelTest < ActiveRecord::TestCase
16
+ self.use_transactional_fixtures = false
17
+ fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :items, :books
18
+
19
+ def test_has_many
20
+ assert authors(:david).categories.include?(categories(:general))
21
+ end
22
+
23
+ def test_has_many_inherited
24
+ assert authors(:mary).categories.include?(categories(:sti_test))
25
+ end
26
+
27
+ def test_inherited_has_many
28
+ assert categories(:sti_test).authors.include?(authors(:mary))
29
+ end
30
+
31
+ def test_has_many_uniq_through_join_model
32
+ assert_equal 2, authors(:mary).categorized_posts.size
33
+ assert_equal 1, authors(:mary).unique_categorized_posts.size
34
+ end
35
+
36
+ def test_has_many_uniq_through_count
37
+ author = authors(:mary)
38
+ assert !authors(:mary).unique_categorized_posts.loaded?
39
+ assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count }
40
+ assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
41
+ assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, :conditions => "title is NULL") }
42
+ assert !authors(:mary).unique_categorized_posts.loaded?
43
+ end
44
+
45
+ unless current_adapter?(:IBM_DBAdapter)
46
+ def test_has_many_uniq_through_find
47
+ assert_equal 1, authors(:mary).unique_categorized_posts.find(:all).size
48
+ end
49
+
50
+ def test_has_many_uniq_through_dynamic_find
51
+ assert_equal 1, authors(:mary).unique_categorized_posts.find_all_by_title("So I was thinking").size
52
+ end
53
+ # LUW: [IBM][CLI Driver][DB2/LINUX] SQL0214N
54
+ # An expression in the ORDER BY clause in the following position,
55
+ # or starting with "DEVELOPERS" in the "ORDER BY" clause is not valid.
56
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
57
+ # SELECT DISTINCT projects.id FROM projects
58
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
59
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
60
+ # ORDER BY developers.created_at
61
+ #
62
+ # i5: [IBM][CLI Driver][AS] SQL0214N
63
+ # An expression in the ORDER BY clause in the following position,
64
+ # or starting with "1" in the "CREATED_AT" clause is not valid.
65
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
66
+ # SELECT DISTINCT projects.id FROM projects
67
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
68
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
69
+ # ORDER BY developers.created_at
70
+ #
71
+ # zOS 9:[IBM][CLI Driver][DB2] SQL0214N
72
+ # An expression in the ORDER BY clause in the following position,
73
+ # or starting with "CREATED_AT" in the "ORDER BY" clause is not valid.
74
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
75
+ # SELECT DISTINCT projects.id FROM projects
76
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
77
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
78
+ # ORDER BY developers.created_at
79
+ #
80
+ end
81
+
82
+ def test_polymorphic_has_many
83
+ assert posts(:welcome).taggings.include?(taggings(:welcome_general))
84
+ end
85
+
86
+ def test_polymorphic_has_one
87
+ assert_equal taggings(:welcome_general), posts(:welcome).tagging
88
+ end
89
+
90
+ def test_polymorphic_belongs_to
91
+ assert_equal posts(:welcome), posts(:welcome).taggings.first.taggable
92
+ end
93
+
94
+ def test_polymorphic_has_many_going_through_join_model
95
+ assert_equal tags(:general), tag = posts(:welcome).tags.first
96
+ assert_no_queries do
97
+ tag.tagging
98
+ end
99
+ end
100
+
101
+ def test_count_polymorphic_has_many
102
+ assert_equal 1, posts(:welcome).taggings.count
103
+ assert_equal 1, posts(:welcome).tags.count
104
+ end
105
+
106
+ def test_polymorphic_has_many_going_through_join_model_with_find
107
+ assert_equal tags(:general), tag = posts(:welcome).tags.find(:first)
108
+ assert_no_queries do
109
+ tag.tagging
110
+ end
111
+ end
112
+
113
+ def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection
114
+ assert_equal tags(:general), tag = posts(:welcome).funky_tags.first
115
+ assert_no_queries do
116
+ tag.tagging
117
+ end
118
+ end
119
+
120
+ def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection_with_find
121
+ assert_equal tags(:general), tag = posts(:welcome).funky_tags.find(:first)
122
+ assert_no_queries do
123
+ tag.tagging
124
+ end
125
+ end
126
+
127
+ def test_polymorphic_has_many_going_through_join_model_with_disabled_include
128
+ assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
129
+ assert_queries 1 do
130
+ tag.tagging
131
+ end
132
+ end
133
+
134
+ def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins
135
+ assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
136
+ tag.author_id
137
+ end
138
+
139
+ def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key
140
+ assert_equal tags(:misc), taggings(:welcome_general).super_tag
141
+ assert_equal tags(:misc), posts(:welcome).super_tags.first
142
+ end
143
+
144
+ def test_polymorphic_has_many_create_model_with_inheritance_and_custom_base_class
145
+ post = SubStiPost.create :title => 'SubStiPost', :body => 'SubStiPost body'
146
+ assert_instance_of SubStiPost, post
147
+
148
+ tagging = tags(:misc).taggings.create(:taggable => post)
149
+ assert_equal "SubStiPost", tagging.taggable_type
150
+ end
151
+
152
+ def test_polymorphic_has_many_going_through_join_model_with_inheritance
153
+ assert_equal tags(:general), posts(:thinking).tags.first
154
+ end
155
+
156
+ def test_polymorphic_has_many_going_through_join_model_with_inheritance_with_custom_class_name
157
+ assert_equal tags(:general), posts(:thinking).funky_tags.first
158
+ end
159
+
160
+ def test_polymorphic_has_many_create_model_with_inheritance
161
+ post = posts(:thinking)
162
+ assert_instance_of SpecialPost, post
163
+
164
+ tagging = tags(:misc).taggings.create(:taggable => post)
165
+ assert_equal "Post", tagging.taggable_type
166
+ end
167
+
168
+ def test_polymorphic_has_one_create_model_with_inheritance
169
+ tagging = tags(:misc).create_tagging(:taggable => posts(:thinking))
170
+ assert_equal "Post", tagging.taggable_type
171
+ end
172
+
173
+ def test_set_polymorphic_has_many
174
+ tagging = tags(:misc).taggings.create
175
+ posts(:thinking).taggings << tagging
176
+ assert_equal "Post", tagging.taggable_type
177
+ end
178
+
179
+ def test_set_polymorphic_has_one
180
+ tagging = tags(:misc).taggings.create
181
+ posts(:thinking).tagging = tagging
182
+ assert_equal "Post", tagging.taggable_type
183
+ end
184
+
185
+ def test_create_polymorphic_has_many_with_scope
186
+ old_count = posts(:welcome).taggings.count
187
+ tagging = posts(:welcome).taggings.create(:tag => tags(:misc))
188
+ assert_equal "Post", tagging.taggable_type
189
+ assert_equal old_count+1, posts(:welcome).taggings.count
190
+ end
191
+
192
+ def test_create_bang_polymorphic_with_has_many_scope
193
+ old_count = posts(:welcome).taggings.count
194
+ tagging = posts(:welcome).taggings.create!(:tag => tags(:misc))
195
+ assert_equal "Post", tagging.taggable_type
196
+ assert_equal old_count+1, posts(:welcome).taggings.count
197
+ end
198
+
199
+ def test_create_polymorphic_has_one_with_scope
200
+ old_count = Tagging.count
201
+ tagging = posts(:welcome).tagging.create(:tag => tags(:misc))
202
+ assert_equal "Post", tagging.taggable_type
203
+ assert_equal old_count+1, Tagging.count
204
+ end
205
+
206
+ def test_delete_polymorphic_has_many_with_delete_all
207
+ assert_equal 1, posts(:welcome).taggings.count
208
+ posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDeleteAll'
209
+ post = find_post_with_dependency(1, :has_many, :taggings, :delete_all)
210
+
211
+ old_count = Tagging.count
212
+ post.destroy
213
+ assert_equal old_count-1, Tagging.count
214
+ assert_equal 0, posts(:welcome).taggings.count
215
+ end
216
+
217
+ def test_delete_polymorphic_has_many_with_destroy
218
+ assert_equal 1, posts(:welcome).taggings.count
219
+ posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDestroy'
220
+ post = find_post_with_dependency(1, :has_many, :taggings, :destroy)
221
+
222
+ old_count = Tagging.count
223
+ post.destroy
224
+ assert_equal old_count-1, Tagging.count
225
+ assert_equal 0, posts(:welcome).taggings.count
226
+ end
227
+
228
+ def test_delete_polymorphic_has_many_with_nullify
229
+ assert_equal 1, posts(:welcome).taggings.count
230
+ posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyNullify'
231
+ post = find_post_with_dependency(1, :has_many, :taggings, :nullify)
232
+
233
+ old_count = Tagging.count
234
+ post.destroy
235
+ assert_equal old_count, Tagging.count
236
+ assert_equal 0, posts(:welcome).taggings.count
237
+ end
238
+
239
+ def test_delete_polymorphic_has_one_with_destroy
240
+ assert posts(:welcome).tagging
241
+ posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneDestroy'
242
+ post = find_post_with_dependency(1, :has_one, :tagging, :destroy)
243
+
244
+ old_count = Tagging.count
245
+ post.destroy
246
+ assert_equal old_count-1, Tagging.count
247
+ assert_nil posts(:welcome).tagging(true)
248
+ end
249
+
250
+ def test_delete_polymorphic_has_one_with_nullify
251
+ assert posts(:welcome).tagging
252
+ posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneNullify'
253
+ post = find_post_with_dependency(1, :has_one, :tagging, :nullify)
254
+
255
+ old_count = Tagging.count
256
+ post.destroy
257
+ assert_equal old_count, Tagging.count
258
+ assert_nil posts(:welcome).tagging(true)
259
+ end
260
+
261
+ def test_has_many_with_piggyback
262
+ assert_equal "2", categories(:sti_test).authors.first.post_id.to_s
263
+ end
264
+
265
+ def test_include_has_many_through
266
+ posts = Post.find(:all, :order => 'posts.id')
267
+ posts_with_authors = Post.find(:all, :include => :authors, :order => 'posts.id')
268
+ assert_equal posts.length, posts_with_authors.length
269
+ posts.length.times do |i|
270
+ assert_equal posts[i].authors.length, assert_no_queries { posts_with_authors[i].authors.length }
271
+ end
272
+ end
273
+
274
+ def test_include_polymorphic_has_one
275
+ post = Post.find_by_id(posts(:welcome).id, :include => :tagging)
276
+ tagging = taggings(:welcome_general)
277
+ assert_no_queries do
278
+ assert_equal tagging, post.tagging
279
+ end
280
+ end
281
+
282
+ def test_include_polymorphic_has_one_defined_in_abstract_parent
283
+ item = Item.find_by_id(items(:dvd).id, :include => :tagging)
284
+ tagging = taggings(:godfather)
285
+ assert_no_queries do
286
+ assert_equal tagging, item.tagging
287
+ end
288
+ end
289
+
290
+ def test_include_polymorphic_has_many_through
291
+ posts = Post.find(:all, :order => 'posts.id')
292
+ posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
293
+ assert_equal posts.length, posts_with_tags.length
294
+ posts.length.times do |i|
295
+ assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
296
+ end
297
+ end
298
+
299
+ def test_include_polymorphic_has_many
300
+ posts = Post.find(:all, :order => 'posts.id')
301
+ posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
302
+ assert_equal posts.length, posts_with_taggings.length
303
+ posts.length.times do |i|
304
+ assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
305
+ end
306
+ end
307
+
308
+ def test_has_many_find_all
309
+ assert_equal [categories(:general)], authors(:david).categories.find(:all)
310
+ end
311
+
312
+ def test_has_many_find_first
313
+ assert_equal categories(:general), authors(:david).categories.find(:first)
314
+ end
315
+
316
+ def test_has_many_with_hash_conditions
317
+ assert_equal categories(:general), authors(:david).categories_like_general.find(:first)
318
+ end
319
+
320
+ def test_has_many_find_conditions
321
+ assert_equal categories(:general), authors(:david).categories.find(:first, :conditions => "categories.name = 'General'")
322
+ assert_equal nil, authors(:david).categories.find(:first, :conditions => "categories.name = 'Technology'")
323
+ end
324
+
325
+ def test_has_many_class_methods_called_by_method_missing
326
+ assert_equal categories(:general), authors(:david).categories.find_all_by_name('General').first
327
+ assert_equal nil, authors(:david).categories.find_by_name('Technology')
328
+ end
329
+
330
+ def test_has_many_array_methods_called_by_method_missing
331
+ assert true, authors(:david).categories.any? { |category| category.name == 'General' }
332
+ assert_nothing_raised { authors(:david).categories.sort }
333
+ end
334
+
335
+ def test_has_many_going_through_join_model_with_custom_foreign_key
336
+ assert_equal [], posts(:thinking).authors
337
+ assert_equal [authors(:mary)], posts(:authorless).authors
338
+ end
339
+
340
+ def test_both_scoped_and_explicit_joins_should_be_respected
341
+ assert_nothing_raised do
342
+ Post.send(:with_scope, :find => {:joins => "left outer join comments on comments.id = posts.id"}) do
343
+ Post.find :all, :select => "comments.id, authors.id", :joins => "left outer join authors on authors.id = posts.author_id"
344
+ end
345
+ end
346
+ end
347
+
348
+ def test_belongs_to_polymorphic_with_counter_cache
349
+ assert_equal 0, posts(:welcome)[:taggings_count]
350
+ tagging = posts(:welcome).taggings.create(:tag => tags(:general))
351
+ assert_equal 1, posts(:welcome, :reload)[:taggings_count]
352
+ tagging.destroy
353
+ assert posts(:welcome, :reload)[:taggings_count].zero?
354
+ end
355
+
356
+ def test_unavailable_through_reflection
357
+ assert_raise(ActiveRecord::HasManyThroughAssociationNotFoundError) { authors(:david).nothings }
358
+ end
359
+
360
+ def test_has_many_through_join_model_with_conditions
361
+ assert_equal [], posts(:welcome).invalid_taggings
362
+ assert_equal [], posts(:welcome).invalid_tags
363
+ end
364
+
365
+ def test_has_many_polymorphic
366
+ assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicError do
367
+ assert_equal posts(:welcome, :thinking), tags(:general).taggables
368
+ end
369
+ assert_raise ActiveRecord::EagerLoadPolymorphicError do
370
+ assert_equal posts(:welcome, :thinking), tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1')
371
+ end
372
+ end
373
+
374
+ def test_has_many_polymorphic_with_source_type
375
+ assert_equal posts(:welcome, :thinking), tags(:general).tagged_posts
376
+ end
377
+
378
+ def test_eager_has_many_polymorphic_with_source_type
379
+ tag_with_include = Tag.find(tags(:general).id, :include => :tagged_posts)
380
+ desired = posts(:welcome, :thinking)
381
+ assert_no_queries do
382
+ assert_equal desired, tag_with_include.tagged_posts
383
+ end
384
+ assert_equal 5, tag_with_include.taggings.length
385
+ end
386
+
387
+ def test_has_many_through_has_many_find_all
388
+ assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first
389
+ end
390
+
391
+ def test_has_many_through_has_many_find_all_with_custom_class
392
+ assert_equal comments(:greetings), authors(:david).funky_comments.find(:all, :order => 'comments.id').first
393
+ end
394
+
395
+ def test_has_many_through_has_many_find_first
396
+ assert_equal comments(:greetings), authors(:david).comments.find(:first, :order => 'comments.id')
397
+ end
398
+
399
+ def test_has_many_through_has_many_find_conditions
400
+ options = { :conditions => "comments.#{QUOTED_TYPE}='SpecialComment'", :order => 'comments.id' }
401
+ assert_equal comments(:does_it_hurt), authors(:david).comments.find(:first, options)
402
+ end
403
+
404
+ def test_has_many_through_has_many_find_by_id
405
+ assert_equal comments(:more_greetings), authors(:david).comments.find(2)
406
+ end
407
+
408
+ def test_has_many_through_polymorphic_has_one
409
+ assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tagging }
410
+ end
411
+
412
+ def test_has_many_through_polymorphic_has_many
413
+ assert_equal taggings(:welcome_general, :thinking_general), authors(:david).taggings.uniq.sort_by { |t| t.id }
414
+ end
415
+
416
+ def test_include_has_many_through_polymorphic_has_many
417
+ author = Author.find_by_id(authors(:david).id, :include => :taggings)
418
+ expected_taggings = taggings(:welcome_general, :thinking_general)
419
+ assert_no_queries do
420
+ assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
421
+ end
422
+ end
423
+
424
+ def test_has_many_through_has_many_through
425
+ assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tags }
426
+ end
427
+
428
+ def test_has_many_through_habtm
429
+ assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).post_categories }
430
+ end
431
+
432
+ unless current_adapter?(:IBM_DBAdapter)
433
+ def test_eager_load_has_many_through_has_many
434
+ author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id'
435
+ SpecialComment.new; VerySpecialComment.new
436
+ assert_no_queries do
437
+ assert_equal [1,2,3,5,6,7,8,9,10], author.comments.collect(&:id)
438
+ end
439
+ end
440
+ # LUW: [IBM][CLI Driver][DB2/LINUX] SQL0214N
441
+ # An expression in the ORDER BY clause in the following position,
442
+ # or starting with "DEVELOPERS" in the "ORDER BY" clause is not valid.
443
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
444
+ # SELECT DISTINCT projects.id FROM projects
445
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
446
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
447
+ # ORDER BY developers.created_at
448
+ #
449
+ # i5: [IBM][CLI Driver][AS] SQL0214N
450
+ # An expression in the ORDER BY clause in the following position,
451
+ # or starting with "1" in the "CREATED_AT" clause is not valid.
452
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
453
+ # SELECT DISTINCT projects.id FROM projects
454
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
455
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
456
+ # ORDER BY developers.created_at
457
+ #
458
+ # zOS 9:[IBM][CLI Driver][DB2] SQL0214N
459
+ # An expression in the ORDER BY clause in the following position,
460
+ # or starting with "CREATED_AT" in the "ORDER BY" clause is not valid.
461
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
462
+ # SELECT DISTINCT projects.id FROM projects
463
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
464
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
465
+ # ORDER BY developers.created_at
466
+ #
467
+ end
468
+
469
+ def test_eager_load_has_many_through_has_many_with_conditions
470
+ post = Post.find(:first, :include => :invalid_tags)
471
+ assert_no_queries do
472
+ post.invalid_tags
473
+ end
474
+ end
475
+
476
+ def test_eager_belongs_to_and_has_one_not_singularized
477
+ assert_nothing_raised do
478
+ Author.find(:first, :include => :author_address)
479
+ AuthorAddress.find(:first, :include => :author)
480
+ end
481
+ end
482
+
483
+ def test_self_referential_has_many_through
484
+ assert_equal [authors(:mary)], authors(:david).favorite_authors
485
+ assert_equal [], authors(:mary).favorite_authors
486
+ end
487
+
488
+ def test_add_to_self_referential_has_many_through
489
+ new_author = Author.create(:name => "Bob")
490
+ authors(:david).author_favorites.create :favorite_author => new_author
491
+ assert_equal new_author, authors(:david).reload.favorite_authors.first
492
+ end
493
+
494
+ def test_has_many_through_uses_conditions_specified_on_the_has_many_association
495
+ author = Author.find(:first)
496
+ assert !author.comments.blank?
497
+ assert author.nonexistant_comments.blank?
498
+ end
499
+
500
+ def test_has_many_through_uses_correct_attributes
501
+ assert_nil posts(:thinking).tags.find_by_name("General").attributes["tag_id"]
502
+ end
503
+
504
+ def test_associating_unsaved_records_with_has_many_through
505
+ saved_post = posts(:thinking)
506
+ new_tag = Tag.new(:name => "new")
507
+
508
+ saved_post.tags << new_tag
509
+ assert !new_tag.new_record? #consistent with habtm!
510
+ assert !saved_post.new_record?
511
+ assert saved_post.tags.include?(new_tag)
512
+
513
+ assert !new_tag.new_record?
514
+ assert saved_post.reload.tags(true).include?(new_tag)
515
+
516
+
517
+ new_post = Post.new(:title => "Association replacmenet works!", :body => "You best believe it.")
518
+ saved_tag = tags(:general)
519
+
520
+ new_post.tags << saved_tag
521
+ assert new_post.new_record?
522
+ assert !saved_tag.new_record?
523
+ assert new_post.tags.include?(saved_tag)
524
+
525
+ new_post.save!
526
+ assert !new_post.new_record?
527
+ assert new_post.reload.tags(true).include?(saved_tag)
528
+
529
+ assert posts(:thinking).tags.build.new_record?
530
+ assert posts(:thinking).tags.new.new_record?
531
+ end
532
+
533
+ def test_create_associate_when_adding_to_has_many_through
534
+ count = posts(:thinking).tags.count
535
+ push = Tag.create!(:name => 'pushme')
536
+ post_thinking = posts(:thinking)
537
+ assert_nothing_raised { post_thinking.tags << push }
538
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
539
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
540
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
541
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
542
+ assert_equal(count + 1, post_thinking.tags.size)
543
+ assert_equal(count + 1, post_thinking.tags(true).size)
544
+
545
+ assert_kind_of Tag, post_thinking.tags.create!(:name => 'foo')
546
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
547
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
548
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
549
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
550
+ assert_equal(count + 2, post_thinking.tags.size)
551
+ assert_equal(count + 2, post_thinking.tags(true).size)
552
+
553
+ assert_nothing_raised { post_thinking.tags.concat(Tag.create!(:name => 'abc'), Tag.create!(:name => 'def')) }
554
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
555
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
556
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
557
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
558
+ assert_equal(count + 4, post_thinking.tags.size)
559
+ assert_equal(count + 4, post_thinking.tags(true).size)
560
+
561
+ # Raises if the wrong reflection name is used to set the Edge belongs_to
562
+ assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
563
+ end
564
+
565
+ def test_has_many_through_collection_size_doesnt_load_target_if_not_loaded
566
+ author = authors(:david)
567
+ assert_equal 9, author.comments.size
568
+ assert !author.comments.loaded?
569
+ end
570
+
571
+ def test_has_many_through_collection_size_uses_counter_cache_if_it_exists
572
+ author = authors(:david)
573
+ author.stubs(:read_attribute).with('comments_count').returns(100)
574
+ assert_equal 100, author.comments.size
575
+ assert !author.comments.loaded?
576
+ end
577
+
578
+ def test_adding_junk_to_has_many_through_should_raise_type_mismatch
579
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags << "Uhh what now?" }
580
+ end
581
+
582
+ def test_adding_to_has_many_through_should_return_self
583
+ tags = posts(:thinking).tags
584
+ assert_equal tags, posts(:thinking).tags.push(tags(:general))
585
+ end
586
+
587
+ def test_delete_associate_when_deleting_from_has_many_through_with_nonstandard_id
588
+ count = books(:awdr).references.count
589
+ references_before = books(:awdr).references
590
+ book = Book.create!(:name => 'Getting Real')
591
+ book_awdr = books(:awdr)
592
+ book_awdr.references << book
593
+ assert_equal(count + 1, book_awdr.references(true).size)
594
+
595
+ assert_nothing_raised { book_awdr.references.delete(book) }
596
+ assert_equal(count, book_awdr.references.size)
597
+ assert_equal(count, book_awdr.references(true).size)
598
+ assert_equal(references_before.sort, book_awdr.references.sort)
599
+ end
600
+
601
+ def test_delete_associate_when_deleting_from_has_many_through
602
+ count = posts(:thinking).tags.count
603
+ tags_before = posts(:thinking).tags
604
+ tag = Tag.create!(:name => 'doomed')
605
+ post_thinking = posts(:thinking)
606
+ post_thinking.tags << tag
607
+ assert_equal(count + 1, post_thinking.taggings(true).size)
608
+ assert_equal(count + 1, post_thinking.tags(true).size)
609
+
610
+ assert_nothing_raised { post_thinking.tags.delete(tag) }
611
+ assert_equal(count, post_thinking.tags.size)
612
+ assert_equal(count, post_thinking.tags(true).size)
613
+ assert_equal(count, post_thinking.taggings(true).size)
614
+ assert_equal(tags_before.sort, post_thinking.tags.sort)
615
+ end
616
+
617
+ def test_delete_associate_when_deleting_from_has_many_through_with_multiple_tags
618
+ count = posts(:thinking).tags.count
619
+ tags_before = posts(:thinking).tags
620
+ doomed = Tag.create!(:name => 'doomed')
621
+ doomed2 = Tag.create!(:name => 'doomed2')
622
+ quaked = Tag.create!(:name => 'quaked')
623
+ post_thinking = posts(:thinking)
624
+ post_thinking.tags << doomed << doomed2
625
+ assert_equal(count + 2, post_thinking.tags(true).size)
626
+
627
+ assert_nothing_raised { post_thinking.tags.delete(doomed, doomed2, quaked) }
628
+ assert_equal(count, post_thinking.tags.size)
629
+ assert_equal(count, post_thinking.tags(true).size)
630
+ assert_equal(tags_before.sort, post_thinking.tags.sort)
631
+ end
632
+
633
+ def test_deleting_junk_from_has_many_through_should_raise_type_mismatch
634
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags.delete("Uhh what now?") }
635
+ end
636
+
637
+ def test_has_many_through_sum_uses_calculations
638
+ assert_nothing_raised { authors(:david).comments.sum(:post_id) }
639
+ end
640
+
641
+ def test_calculations_on_has_many_through_should_disambiguate_fields
642
+ assert_nothing_raised { authors(:david).categories.maximum(:id) }
643
+ end
644
+
645
+ def test_calculations_on_has_many_through_should_not_disambiguate_fields_unless_necessary
646
+ assert_nothing_raised { authors(:david).categories.maximum("categories.id") }
647
+ end
648
+
649
+ def test_has_many_through_has_many_with_sti
650
+ assert_equal [comments(:does_it_hurt)], authors(:david).special_post_comments
651
+ end
652
+
653
+ def test_uniq_has_many_through_should_retain_order
654
+ comment_ids = authors(:david).comments.map(&:id)
655
+ assert_equal comment_ids.sort, authors(:david).ordered_uniq_comments.map(&:id)
656
+
657
+ unless current_adapter?(:IBM_DBAdapter)
658
+ assert_equal comment_ids.sort.reverse, authors(:david).ordered_uniq_comments_desc.map(&:id)
659
+ # LUW: [IBM][CLI Driver][DB2/LINUX] SQL0214N
660
+ # An expression in the ORDER BY clause in the following position,
661
+ # or starting with "DEVELOPERS" in the "ORDER BY" clause is not valid.
662
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
663
+ # SELECT DISTINCT projects.id FROM projects
664
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
665
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
666
+ # ORDER BY developers.created_at
667
+ #
668
+ # i5: [IBM][CLI Driver][AS] SQL0214N
669
+ # An expression in the ORDER BY clause in the following position,
670
+ # or starting with "1" in the "CREATED_AT" clause is not valid.
671
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
672
+ # SELECT DISTINCT projects.id FROM projects
673
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
674
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
675
+ # ORDER BY developers.created_at
676
+ #
677
+ # zOS 9:[IBM][CLI Driver][DB2] SQL0214N
678
+ # An expression in the ORDER BY clause in the following position,
679
+ # or starting with "CREATED_AT" in the "ORDER BY" clause is not valid.
680
+ # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
681
+ # SELECT DISTINCT projects.id FROM projects
682
+ # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
683
+ # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
684
+ # ORDER BY developers.created_at
685
+ #
686
+ end
687
+ end
688
+
689
+ def test_polymorphic_has_many
690
+ expected = taggings(:welcome_general)
691
+ p = Post.find(posts(:welcome).id, :include => :taggings)
692
+ assert_no_queries {assert p.taggings.include?(expected)}
693
+ assert posts(:welcome).taggings.include?(taggings(:welcome_general))
694
+ end
695
+
696
+ def test_polymorphic_has_one
697
+ expected = posts(:welcome)
698
+
699
+ tagging = Tagging.find(taggings(:welcome_general).id, :include => :taggable)
700
+ assert_no_queries { assert_equal expected, tagging.taggable}
701
+ end
702
+
703
+ def test_polymorphic_belongs_to
704
+ p = Post.find(posts(:welcome).id, :include => {:taggings => :taggable})
705
+ assert_no_queries {assert_equal posts(:welcome), p.taggings.first.taggable}
706
+ end
707
+
708
+ def test_preload_polymorphic_has_many_through
709
+ posts = Post.find(:all, :order => 'posts.id')
710
+ posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
711
+ assert_equal posts.length, posts_with_tags.length
712
+ posts.length.times do |i|
713
+ assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
714
+ end
715
+ end
716
+
717
+ def test_preload_polymorph_many_types
718
+ taggings = Tagging.find :all, :include => :taggable, :conditions => ['taggable_type != ?', 'FakeModel']
719
+ assert_no_queries do
720
+ taggings.first.taggable.id
721
+ taggings[1].taggable.id
722
+ end
723
+
724
+ taggables = taggings.map(&:taggable)
725
+ assert taggables.include?(items(:dvd))
726
+ assert taggables.include?(posts(:welcome))
727
+ end
728
+
729
+ def test_preload_nil_polymorphic_belongs_to
730
+ assert_nothing_raised do
731
+ taggings = Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL'])
732
+ end
733
+ end
734
+
735
+ def test_preload_polymorphic_has_many
736
+ posts = Post.find(:all, :order => 'posts.id')
737
+ posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
738
+ assert_equal posts.length, posts_with_taggings.length
739
+ posts.length.times do |i|
740
+ assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
741
+ end
742
+ end
743
+
744
+ def test_belongs_to_shared_parent
745
+ comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 1')
746
+ assert_no_queries do
747
+ assert_equal comments.first.post, comments[1].post
748
+ end
749
+ end
750
+
751
+ def test_has_many_through_include_uses_array_include_after_loaded
752
+ david = authors(:david)
753
+ david.categories.class # force load target
754
+
755
+ category = david.categories.first
756
+
757
+ assert_no_queries do
758
+ assert david.categories.loaded?
759
+ assert david.categories.include?(category)
760
+ end
761
+ end
762
+
763
+ def test_has_many_through_include_checks_if_record_exists_if_target_not_loaded
764
+ david = authors(:david)
765
+ category = david.categories.first
766
+
767
+ david.reload
768
+ assert ! david.categories.loaded?
769
+ assert_queries(1) do
770
+ assert david.categories.include?(category)
771
+ end
772
+ assert ! david.categories.loaded?
773
+ end
774
+
775
+ unless current_adapter?(:IBM_DBAdapter) #works fine stand alone, however when run as part of whole suite it breaks unique constraint
776
+ def test_has_many_through_include_returns_false_for_non_matching_record_to_verify_scoping
777
+ david = authors(:david)
778
+ category = Category.create!(:name => 'Not Associated')
779
+
780
+ assert ! david.categories.loaded?
781
+ assert ! david.categories.include?(category)
782
+ end
783
+ end
784
+ def test_has_many_through_goes_through_all_sti_classes
785
+ sub_sti_post = SubStiPost.create!(:title => 'test', :body => 'test', :author_id => 1)
786
+ new_comment = sub_sti_post.comments.create(:body => 'test')
787
+
788
+ assert_equal [9, 10, new_comment.id], authors(:david).sti_post_comments.map(&:id).sort
789
+ end
790
+
791
+ private
792
+ # create dynamic Post models to allow different dependency options
793
+ def find_post_with_dependency(post_id, association, association_name, dependency)
794
+ class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
795
+ Post.find(post_id).update_attribute :type, class_name
796
+ klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
797
+ klass.set_table_name 'posts'
798
+ klass.send(association, association_name, :as => :taggable, :dependent => dependency)
799
+ klass.find(post_id)
800
+ end
801
+ end