sequel 3.31.0 → 3.32.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/CHANGELOG +54 -0
  2. data/MIT-LICENSE +1 -1
  3. data/doc/advanced_associations.rdoc +17 -0
  4. data/doc/association_basics.rdoc +74 -30
  5. data/doc/release_notes/3.32.0.txt +202 -0
  6. data/doc/schema_modification.rdoc +1 -1
  7. data/lib/sequel/adapters/jdbc/db2.rb +7 -0
  8. data/lib/sequel/adapters/jdbc/derby.rb +13 -0
  9. data/lib/sequel/adapters/jdbc/h2.rb +10 -1
  10. data/lib/sequel/adapters/jdbc/hsqldb.rb +7 -0
  11. data/lib/sequel/adapters/jdbc/oracle.rb +7 -0
  12. data/lib/sequel/adapters/mock.rb +4 -0
  13. data/lib/sequel/adapters/mysql.rb +3 -0
  14. data/lib/sequel/adapters/oracle.rb +7 -3
  15. data/lib/sequel/adapters/shared/db2.rb +9 -2
  16. data/lib/sequel/adapters/shared/mssql.rb +48 -2
  17. data/lib/sequel/adapters/shared/mysql.rb +24 -4
  18. data/lib/sequel/adapters/shared/oracle.rb +7 -6
  19. data/lib/sequel/adapters/shared/progress.rb +1 -1
  20. data/lib/sequel/adapters/shared/sqlite.rb +16 -10
  21. data/lib/sequel/core.rb +22 -0
  22. data/lib/sequel/database/query.rb +13 -4
  23. data/lib/sequel/dataset/actions.rb +20 -11
  24. data/lib/sequel/dataset/mutation.rb +7 -1
  25. data/lib/sequel/dataset/prepared_statements.rb +11 -0
  26. data/lib/sequel/dataset/sql.rb +21 -24
  27. data/lib/sequel/extensions/query.rb +1 -1
  28. data/lib/sequel/model.rb +5 -2
  29. data/lib/sequel/model/associations.rb +70 -16
  30. data/lib/sequel/model/base.rb +11 -6
  31. data/lib/sequel/plugins/active_model.rb +13 -1
  32. data/lib/sequel/plugins/composition.rb +43 -10
  33. data/lib/sequel/plugins/many_through_many.rb +4 -1
  34. data/lib/sequel/plugins/nested_attributes.rb +65 -10
  35. data/lib/sequel/plugins/serialization.rb +13 -8
  36. data/lib/sequel/plugins/serialization_modification_detection.rb +22 -10
  37. data/lib/sequel/version.rb +1 -1
  38. data/spec/adapters/mssql_spec.rb +33 -10
  39. data/spec/adapters/mysql_spec.rb +111 -91
  40. data/spec/adapters/oracle_spec.rb +18 -0
  41. data/spec/core/database_spec.rb +1 -0
  42. data/spec/core/dataset_spec.rb +110 -15
  43. data/spec/extensions/active_model_spec.rb +13 -0
  44. data/spec/extensions/many_through_many_spec.rb +14 -14
  45. data/spec/extensions/query_spec.rb +6 -0
  46. data/spec/extensions/serialization_modification_detection_spec.rb +36 -1
  47. data/spec/extensions/serialization_spec.rb +9 -0
  48. data/spec/integration/associations_test.rb +278 -154
  49. data/spec/integration/dataset_test.rb +39 -2
  50. data/spec/integration/plugin_test.rb +63 -3
  51. data/spec/integration/prepared_statement_test.rb +10 -3
  52. data/spec/integration/schema_test.rb +61 -14
  53. data/spec/integration/transaction_test.rb +10 -0
  54. data/spec/model/associations_spec.rb +170 -80
  55. data/spec/model/hooks_spec.rb +40 -0
  56. metadata +4 -2
@@ -208,6 +208,15 @@ describe "Serialization plugin" do
208
208
  o.deserialized_values.length.should == 0
209
209
  end
210
210
 
211
+ it "should clear the deserialized columns when refreshing after saving a new object" do
212
+ @c.set_primary_key :id
213
+ @c.plugin :serialization, :yaml, :abc, :def
214
+ o = @c.new(:abc => "--- 1\n", :def => "--- hello\n")
215
+ o.deserialized_values.length.should == 2
216
+ o.save
217
+ o.deserialized_values.length.should == 0
218
+ end
219
+
211
220
  it "should raise an error if calling internal serialization methods with bad columns" do
212
221
  @c.set_primary_key :id
213
222
  @c.plugin :serialization
@@ -102,60 +102,18 @@ shared_examples_for "eager limit strategies" do
102
102
  end
103
103
  end
104
104
 
105
- shared_examples_for "regular and composite key associations" do
106
- specify "should return no objects if none are associated" do
107
- @album.artist.should == nil
108
- @artist.first_album.should == nil
109
- @artist.albums.should == []
110
- @album.tags.should == []
111
- @album.alias_tags.should == []
112
- @tag.albums.should == []
113
- end
114
-
115
- specify "should have add and set methods work any associated objects" do
116
- @album.update(:artist => @artist)
117
- @album.add_tag(@tag)
118
-
119
- @album.reload
120
- @artist.reload
121
- @tag.reload
122
-
123
- @album.artist.should == @artist
124
- @artist.first_album.should == @album
125
- @artist.albums.should == [@album]
126
- @album.tags.should == [@tag]
127
- @album.alias_tags.should == [@tag]
128
- @tag.albums.should == [@album]
129
- end
130
-
131
- specify "should work correctly with prepared_statements_association plugin" do
132
- @album.update(:artist => @artist)
133
- @album.add_tag(@tag)
134
-
135
- @album.reload
136
- @artist.reload
137
- @tag.reload
138
-
139
- [Tag, Album, Artist].each{|x| x.plugin :prepared_statements_associations}
140
- @album.artist.should == @artist
141
- @artist.first_album.should == @album
142
- @artist.albums.should == [@album]
143
- @album.tags.should == [@tag]
144
- @album.alias_tags.should == [@tag]
145
- @tag.albums.should == [@album]
146
- end
147
-
105
+ shared_examples_for "filtering/excluding by associations" do
148
106
  specify "should work correctly when filtering by associations" do
149
107
  @album.update(:artist => @artist)
150
108
  @album.add_tag(@tag)
151
109
 
152
- Artist.filter(:albums=>@album).all.should == [@artist]
153
- Artist.filter(:first_album=>@album).all.should == [@artist]
154
- Album.filter(:artist=>@artist).all.should == [@album]
155
- Album.filter(:tags=>@tag).all.should == [@album]
156
- Album.filter(:alias_tags=>@tag).all.should == [@album]
157
- Tag.filter(:albums=>@album).all.should == [@tag]
158
- Album.filter(:artist=>@artist, :tags=>@tag).all.should == [@album]
110
+ @Artist.filter(:albums=>@album).all.should == [@artist]
111
+ @Artist.filter(:first_album=>@album).all.should == [@artist]
112
+ @Album.filter(:artist=>@artist).all.should == [@album]
113
+ @Album.filter(:tags=>@tag).all.should == [@album]
114
+ @Album.filter(:alias_tags=>@tag).all.should == [@album]
115
+ @Tag.filter(:albums=>@album).all.should == [@tag]
116
+ @Album.filter(:artist=>@artist, :tags=>@tag).all.should == [@album]
159
117
  @artist.albums_dataset.filter(:tags=>@tag).all.should == [@album]
160
118
  end
161
119
 
@@ -164,13 +122,13 @@ shared_examples_for "regular and composite key associations" do
164
122
  @album.add_tag(@tag)
165
123
  album, artist, tag = @pr.call
166
124
 
167
- Artist.exclude(:albums=>@album).all.should == [artist]
168
- Artist.exclude(:first_album=>@album).all.should == [artist]
169
- Album.exclude(:artist=>@artist).all.should == [album]
170
- Album.exclude(:tags=>@tag).all.should == [album]
171
- Album.exclude(:alias_tags=>@tag).all.should == [album]
172
- Tag.exclude(:albums=>@album).all.should == [tag]
173
- Album.exclude(:artist=>@artist, :tags=>@tag).all.should == [album]
125
+ @Artist.exclude(:albums=>@album).all.should == [artist]
126
+ @Artist.exclude(:first_album=>@album).all.should == [artist]
127
+ @Album.exclude(:artist=>@artist).all.should == [album]
128
+ @Album.exclude(:tags=>@tag).all.should == [album]
129
+ @Album.exclude(:alias_tags=>@tag).all.should == [album]
130
+ @Tag.exclude(:albums=>@album).all.should == [tag]
131
+ @Album.exclude(:artist=>@artist, :tags=>@tag).all.should == [album]
174
132
  end
175
133
 
176
134
  specify "should work correctly when filtering by multiple associations" do
@@ -178,87 +136,87 @@ shared_examples_for "regular and composite key associations" do
178
136
  @album.update(:artist => @artist)
179
137
  @album.add_tag(@tag)
180
138
 
181
- Artist.filter(:albums=>[@album, album]).all.should == [@artist]
182
- Artist.filter(:first_album=>[@album, album]).all.should == [@artist]
183
- Album.filter(:artist=>[@artist, artist]).all.should == [@album]
184
- Album.filter(:tags=>[@tag, tag]).all.should == [@album]
185
- Album.filter(:alias_tags=>[@tag, tag]).all.should == [@album]
186
- Tag.filter(:albums=>[@album, album]).all.should == [@tag]
187
- Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [@album]
139
+ @Artist.filter(:albums=>[@album, album]).all.should == [@artist]
140
+ @Artist.filter(:first_album=>[@album, album]).all.should == [@artist]
141
+ @Album.filter(:artist=>[@artist, artist]).all.should == [@album]
142
+ @Album.filter(:tags=>[@tag, tag]).all.should == [@album]
143
+ @Album.filter(:alias_tags=>[@tag, tag]).all.should == [@album]
144
+ @Tag.filter(:albums=>[@album, album]).all.should == [@tag]
145
+ @Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [@album]
188
146
  @artist.albums_dataset.filter(:tags=>[@tag, tag]).all.should == [@album]
189
147
 
190
148
  album.add_tag(tag)
191
149
 
192
- Artist.filter(:albums=>[@album, album]).all.should == [@artist]
193
- Artist.filter(:first_album=>[@album, album]).all.should == [@artist]
194
- Album.filter(:artist=>[@artist, artist]).all.should == [@album]
195
- Album.filter(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
196
- Album.filter(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
197
- Tag.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
198
- Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [@album]
150
+ @Artist.filter(:albums=>[@album, album]).all.should == [@artist]
151
+ @Artist.filter(:first_album=>[@album, album]).all.should == [@artist]
152
+ @Album.filter(:artist=>[@artist, artist]).all.should == [@album]
153
+ @Album.filter(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
154
+ @Album.filter(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
155
+ @Tag.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
156
+ @Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [@album]
199
157
 
200
158
  album.update(:artist => artist)
201
159
 
202
- Artist.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
203
- Artist.filter(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
204
- Album.filter(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [@album, album]
205
- Album.filter(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
206
- Album.filter(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
207
- Tag.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
208
- Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
160
+ @Artist.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
161
+ @Artist.filter(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
162
+ @Album.filter(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [@album, album]
163
+ @Album.filter(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
164
+ @Album.filter(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
165
+ @Tag.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
166
+ @Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
209
167
  end
210
168
 
211
169
  specify "should work correctly when excluding by multiple associations" do
212
170
  album, artist, tag = @pr.call
213
171
 
214
- Artist.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
215
- Artist.exclude(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
216
- Album.exclude(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [@album, album]
217
- Album.exclude(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
218
- Album.exclude(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
219
- Tag.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
220
- Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
172
+ @Artist.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
173
+ @Artist.exclude(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
174
+ @Album.exclude(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [@album, album]
175
+ @Album.exclude(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
176
+ @Album.exclude(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
177
+ @Tag.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
178
+ @Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
221
179
 
222
180
  @album.update(:artist => @artist)
223
181
  @album.add_tag(@tag)
224
182
 
225
- Artist.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [artist]
226
- Artist.exclude(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [artist]
227
- Album.exclude(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [album]
228
- Album.exclude(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
229
- Album.exclude(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
230
- Tag.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [tag]
231
- Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
183
+ @Artist.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [artist]
184
+ @Artist.exclude(:first_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [artist]
185
+ @Album.exclude(:artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [album]
186
+ @Album.exclude(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
187
+ @Album.exclude(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
188
+ @Tag.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [tag]
189
+ @Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
232
190
 
233
191
  album.add_tag(tag)
234
192
 
235
- Artist.exclude(:albums=>[@album, album]).all.should == [artist]
236
- Artist.exclude(:first_album=>[@album, album]).all.should == [artist]
237
- Album.exclude(:artist=>[@artist, artist]).all.should == [album]
238
- Album.exclude(:tags=>[@tag, tag]).all.should == []
239
- Album.exclude(:alias_tags=>[@tag, tag]).all.should == []
240
- Tag.exclude(:albums=>[@album, album]).all.should == []
241
- Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [album]
193
+ @Artist.exclude(:albums=>[@album, album]).all.should == [artist]
194
+ @Artist.exclude(:first_album=>[@album, album]).all.should == [artist]
195
+ @Album.exclude(:artist=>[@artist, artist]).all.should == [album]
196
+ @Album.exclude(:tags=>[@tag, tag]).all.should == []
197
+ @Album.exclude(:alias_tags=>[@tag, tag]).all.should == []
198
+ @Tag.exclude(:albums=>[@album, album]).all.should == []
199
+ @Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [album]
242
200
 
243
201
  album.update(:artist => artist)
244
202
 
245
- Artist.exclude(:albums=>[@album, album]).all.should == []
246
- Artist.exclude(:first_album=>[@album, album]).all.should == []
247
- Album.exclude(:artist=>[@artist, artist]).all.should == []
248
- Album.exclude(:tags=>[@tag, tag]).all.should == []
249
- Album.exclude(:alias_tags=>[@tag, tag]).all.should == []
250
- Tag.exclude(:albums=>[@album, album]).all.should == []
251
- Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == []
203
+ @Artist.exclude(:albums=>[@album, album]).all.should == []
204
+ @Artist.exclude(:first_album=>[@album, album]).all.should == []
205
+ @Album.exclude(:artist=>[@artist, artist]).all.should == []
206
+ @Album.exclude(:tags=>[@tag, tag]).all.should == []
207
+ @Album.exclude(:alias_tags=>[@tag, tag]).all.should == []
208
+ @Tag.exclude(:albums=>[@album, album]).all.should == []
209
+ @Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == []
252
210
  end
253
211
 
254
212
  specify "should work correctly when excluding by associations in regards to NULL values" do
255
- Artist.exclude(:albums=>@album).all.should == [@artist]
256
- Artist.exclude(:first_album=>@album).all.should == [@artist]
257
- Album.exclude(:artist=>@artist).all.should == [@album]
258
- Album.exclude(:tags=>@tag).all.should == [@album]
259
- Album.exclude(:alias_tags=>@tag).all.should == [@album]
260
- Tag.exclude(:albums=>@album).all.should == [@tag]
261
- Album.exclude(:artist=>@artist, :tags=>@tag).all.should == [@album]
213
+ @Artist.exclude(:albums=>@album).all.should == [@artist]
214
+ @Artist.exclude(:first_album=>@album).all.should == [@artist]
215
+ @Album.exclude(:artist=>@artist).all.should == [@album]
216
+ @Album.exclude(:tags=>@tag).all.should == [@album]
217
+ @Album.exclude(:alias_tags=>@tag).all.should == [@album]
218
+ @Tag.exclude(:albums=>@album).all.should == [@tag]
219
+ @Album.exclude(:artist=>@artist, :tags=>@tag).all.should == [@album]
262
220
 
263
221
  @album.update(:artist => @artist)
264
222
  @artist.albums_dataset.exclude(:tags=>@tag).all.should == [@album]
@@ -266,16 +224,16 @@ shared_examples_for "regular and composite key associations" do
266
224
 
267
225
  specify "should handle NULL values in join table correctly when filtering/excluding many_to_many associations" do
268
226
  @ins.call
269
- Album.exclude(:tags=>@tag).all.should == [@album]
270
- Album.exclude(:alias_tags=>@tag).all.should == [@album]
227
+ @Album.exclude(:tags=>@tag).all.should == [@album]
228
+ @Album.exclude(:alias_tags=>@tag).all.should == [@album]
271
229
  @album.add_tag(@tag)
272
- Album.filter(:tags=>@tag).all.should == [@album]
273
- Album.filter(:alias_tags=>@tag).all.should == [@album]
230
+ @Album.filter(:tags=>@tag).all.should == [@album]
231
+ @Album.filter(:alias_tags=>@tag).all.should == [@album]
274
232
  album, artist, tag = @pr.call
275
- Album.exclude(:tags=>@tag).all.should == [album]
276
- Album.exclude(:alias_tags=>@tag).all.should == [album]
277
- Album.exclude(:tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
278
- Album.exclude(:alias_tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
233
+ @Album.exclude(:tags=>@tag).all.should == [album]
234
+ @Album.exclude(:alias_tags=>@tag).all.should == [album]
235
+ @Album.exclude(:tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
236
+ @Album.exclude(:alias_tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
279
237
  end
280
238
 
281
239
  specify "should work correctly when filtering by association datasets" do
@@ -285,24 +243,24 @@ shared_examples_for "regular and composite key associations" do
285
243
  album.add_tag(tag)
286
244
  album.update(:artist => artist)
287
245
 
288
- Artist.filter(:albums=>Album.dataset).all.sort_by{|x| x.pk}.should == [@artist, artist]
289
- Artist.filter(:albums=>Album.dataset.filter(Array(Album.primary_key).zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [artist]
290
- Artist.filter(:albums=>Album.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
291
- Artist.filter(:first_album=>Album.dataset).all.sort_by{|x| x.pk}.should == [@artist, artist]
292
- Artist.filter(:first_album=>Album.dataset.filter(Array(Album.primary_key).zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [artist]
293
- Artist.filter(:first_album=>Album.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
294
- Album.filter(:artist=>Artist.dataset).all.sort_by{|x| x.pk}.should == [@album, album]
295
- Album.filter(:artist=>Artist.dataset.filter(Array(Artist.primary_key).zip(Array(artist.pk)))).all.sort_by{|x| x.pk}.should == [album]
296
- Album.filter(:artist=>Artist.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
297
- Album.filter(:tags=>Tag.dataset).all.sort_by{|x| x.pk}.should == [@album, album]
298
- Album.filter(:tags=>Tag.dataset.filter(Array(Tag.primary_key).zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
299
- Album.filter(:tags=>Tag.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
300
- Album.filter(:alias_tags=>Tag.dataset).all.sort_by{|x| x.pk}.should == [@album, album]
301
- Album.filter(:alias_tags=>Tag.dataset.filter(Array(Tag.primary_key).zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
302
- Album.filter(:alias_tags=>Tag.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
303
- Tag.filter(:albums=>Album.dataset).all.sort_by{|x| x.pk}.should == [@tag, tag]
304
- Tag.filter(:albums=>Album.dataset.filter(Array(Album.primary_key).zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [tag]
305
- Tag.filter(:albums=>Album.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
246
+ @Artist.filter(:albums=>@Album).all.sort_by{|x| x.pk}.should == [@artist, artist]
247
+ @Artist.filter(:albums=>@Album.filter(Array(Album.primary_key).map{|k| k.qualify(Album.table_name)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [artist]
248
+ @Artist.filter(:albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
249
+ @Artist.filter(:first_album=>@Album).all.sort_by{|x| x.pk}.should == [@artist, artist]
250
+ @Artist.filter(:first_album=>@Album.filter(Array(Album.primary_key).map{|k| k.qualify(Album.table_name)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [artist]
251
+ @Artist.filter(:first_album=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
252
+ @Album.filter(:artist=>@Artist).all.sort_by{|x| x.pk}.should == [@album, album]
253
+ @Album.filter(:artist=>@Artist.filter(Array(Artist.primary_key).map{|k| k.qualify(Artist.table_name)}.zip(Array(artist.pk)))).all.sort_by{|x| x.pk}.should == [album]
254
+ @Album.filter(:artist=>@Artist.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
255
+ @Album.filter(:tags=>@Tag).all.sort_by{|x| x.pk}.should == [@album, album]
256
+ @Album.filter(:tags=>@Tag.filter(Array(Tag.primary_key).map{|k| k.qualify(Tag.table_name)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
257
+ @Album.filter(:tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
258
+ @Album.filter(:alias_tags=>@Tag).all.sort_by{|x| x.pk}.should == [@album, album]
259
+ @Album.filter(:alias_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| k.qualify(Tag.table_name)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
260
+ @Album.filter(:alias_tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
261
+ @Tag.filter(:albums=>@Album).all.sort_by{|x| x.pk}.should == [@tag, tag]
262
+ @Tag.filter(:albums=>@Album.filter(Array(Album.primary_key).map{|k| k.qualify(Album.table_name)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [tag]
263
+ @Tag.filter(:albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
306
264
  end
307
265
 
308
266
  specify "should work correctly when excluding by association datasets" do
@@ -312,21 +270,65 @@ shared_examples_for "regular and composite key associations" do
312
270
  album.add_tag(tag)
313
271
  album.update(:artist => artist)
314
272
 
315
- Artist.exclude(:albums=>Album.dataset).all.sort_by{|x| x.pk}.should == []
316
- Artist.exclude(:albums=>Album.dataset.filter(Array(Album.primary_key).zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@artist]
317
- Artist.exclude(:albums=>Album.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@artist, artist]
318
- Album.exclude(:artist=>Artist.dataset).all.sort_by{|x| x.pk}.should == []
319
- Album.exclude(:artist=>Artist.dataset.filter(Array(Artist.primary_key).zip(Array(artist.pk)))).all.sort_by{|x| x.pk}.should == [@album]
320
- Album.exclude(:artist=>Artist.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
321
- Album.exclude(:tags=>Tag.dataset).all.sort_by{|x| x.pk}.should == []
322
- Album.exclude(:tags=>Tag.dataset.filter(Array(Tag.primary_key).zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@album]
323
- Album.exclude(:tags=>Tag.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
324
- Album.exclude(:alias_tags=>Tag.dataset).all.sort_by{|x| x.pk}.should == []
325
- Album.exclude(:alias_tags=>Tag.dataset.filter(Array(Tag.primary_key).zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@album]
326
- Album.exclude(:alias_tags=>Tag.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
327
- Tag.exclude(:albums=>Album.dataset).all.sort_by{|x| x.pk}.should == []
328
- Tag.exclude(:albums=>Album.dataset.filter(Array(Album.primary_key).zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@tag]
329
- Tag.exclude(:albums=>Album.dataset.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@tag, tag]
273
+ @Artist.exclude(:albums=>@Album).all.sort_by{|x| x.pk}.should == []
274
+ @Artist.exclude(:albums=>@Album.filter(Array(Album.primary_key).map{|k| k.qualify(Album.table_name)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@artist]
275
+ @Artist.exclude(:albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@artist, artist]
276
+ @Album.exclude(:artist=>@Artist).all.sort_by{|x| x.pk}.should == []
277
+ @Album.exclude(:artist=>@Artist.filter(Array(Artist.primary_key).map{|k| k.qualify(Artist.table_name)}.zip(Array(artist.pk)))).all.sort_by{|x| x.pk}.should == [@album]
278
+ @Album.exclude(:artist=>@Artist.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
279
+ @Album.exclude(:tags=>@Tag).all.sort_by{|x| x.pk}.should == []
280
+ @Album.exclude(:tags=>@Tag.filter(Array(Tag.primary_key).map{|k| k.qualify(Tag.table_name)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@album]
281
+ @Album.exclude(:tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
282
+ @Album.exclude(:alias_tags=>@Tag).all.sort_by{|x| x.pk}.should == []
283
+ @Album.exclude(:alias_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| k.qualify(Tag.table_name)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@album]
284
+ @Album.exclude(:alias_tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
285
+ @Tag.exclude(:albums=>@Album).all.sort_by{|x| x.pk}.should == []
286
+ @Tag.exclude(:albums=>@Album.filter(Array(Album.primary_key).map{|k| k.qualify(Album.table_name)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@tag]
287
+ @Tag.exclude(:albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@tag, tag]
288
+ end
289
+ end
290
+
291
+ shared_examples_for "regular and composite key associations" do
292
+ specify "should return no objects if none are associated" do
293
+ @album.artist.should == nil
294
+ @artist.first_album.should == nil
295
+ @artist.albums.should == []
296
+ @album.tags.should == []
297
+ @album.alias_tags.should == []
298
+ @tag.albums.should == []
299
+ end
300
+
301
+ specify "should have add and set methods work any associated objects" do
302
+ @album.update(:artist => @artist)
303
+ @album.add_tag(@tag)
304
+
305
+ @album.reload
306
+ @artist.reload
307
+ @tag.reload
308
+
309
+ @album.artist.should == @artist
310
+ @artist.first_album.should == @album
311
+ @artist.albums.should == [@album]
312
+ @album.tags.should == [@tag]
313
+ @album.alias_tags.should == [@tag]
314
+ @tag.albums.should == [@album]
315
+ end
316
+
317
+ specify "should work correctly with prepared_statements_association plugin" do
318
+ @album.update(:artist => @artist)
319
+ @album.add_tag(@tag)
320
+
321
+ @album.reload
322
+ @artist.reload
323
+ @tag.reload
324
+
325
+ [Tag, Album, Artist].each{|x| x.plugin :prepared_statements_associations}
326
+ @album.artist.should == @artist
327
+ @artist.first_album.should == @album
328
+ @artist.albums.should == [@album]
329
+ @album.tags.should == [@tag]
330
+ @album.alias_tags.should == [@tag]
331
+ @tag.albums.should == [@album]
330
332
  end
331
333
 
332
334
  specify "should have working dataset associations" do
@@ -442,6 +444,30 @@ shared_examples_for "regular and composite key associations" do
442
444
  a.first.albums.first.artist.should == @artist
443
445
  end
444
446
 
447
+ describe "when filtering/excluding by associations" do
448
+ before do
449
+ @Artist = Artist.dataset
450
+ @Album = Album.dataset
451
+ @Tag = Tag.dataset
452
+ end
453
+
454
+ it_should_behave_like "filtering/excluding by associations"
455
+ end
456
+
457
+ describe "when filtering/excluding by associations when joining" do
458
+ def self_join(c)
459
+ c.join(c.table_name.as(:b), Array(c.primary_key).zip(Array(c.primary_key))).select_all(c.table_name)
460
+ end
461
+
462
+ before do
463
+ @Artist = self_join(Artist)
464
+ @Album = self_join(Album)
465
+ @Tag = self_join(Tag)
466
+ end
467
+
468
+ it_should_behave_like "filtering/excluding by associations"
469
+ end
470
+
445
471
  describe "with no :eager_limit_strategy" do
446
472
  it_should_behave_like "eager limit strategies"
447
473
  end
@@ -838,3 +864,101 @@ describe "Sequel::Model Composite Key Associations" do
838
864
  proc{@artist.remove_album(@album)}.should raise_error(Sequel::Error)
839
865
  end
840
866
  end
867
+
868
+ describe "Sequel::Model Associations with clashing column names" do
869
+ before(:all) do
870
+ @db = INTEGRATION_DB
871
+ [:bars_foos, :bars, :foos].each{|t| @db.drop_table(t) rescue nil}
872
+ @db.create_table(:foos) do
873
+ primary_key :id
874
+ Integer :object_id
875
+ end
876
+ @db.create_table(:bars) do
877
+ primary_key :id
878
+ Integer :object_id
879
+ end
880
+ @db.create_table(:bars_foos) do
881
+ Integer :foo_id
882
+ Integer :object_id
883
+ primary_key [:foo_id, :object_id]
884
+ end
885
+ end
886
+ before do
887
+ [:bars_foos, :bars, :foos].each{|t| @db[t].delete}
888
+ @Foo = Class.new(Sequel::Model(:foos))
889
+ @Bar = Class.new(Sequel::Model(:bars))
890
+ @Foo.def_column_alias(:obj_id, :object_id)
891
+ @Bar.def_column_alias(:obj_id, :object_id)
892
+ @Foo.one_to_many :bars, :primary_key=>:obj_id, :primary_key_column=>:object_id, :key=>:object_id, :key_method=>:obj_id, :eager_loader_key=>:object_id, :class=>@Bar
893
+ @Foo.one_to_one :bar, :primary_key=>:obj_id, :primary_key_column=>:object_id, :key=>:object_id, :key_method=>:obj_id, :eager_loader_key=>:object_id, :class=>@Bar
894
+ @Bar.many_to_one :foo, :key=>:obj_id, :key_column=>:object_id, :primary_key=>:object_id, :primary_key_method=>:obj_id, :class=>@Foo
895
+ @Foo.many_to_many :mtmbars, :join_table=>:bars_foos, :left_primary_key=>:obj_id, :left_primary_key_column=>:object_id, :right_primary_key=>:object_id, :right_primary_key_method=>:obj_id, :left_key=>:foo_id, :right_key=>:object_id, :eager_loader_key=>:object_id, :class=>@Bar
896
+ @Bar.many_to_many :mtmfoos, :join_table=>:bars_foos, :left_primary_key=>:obj_id, :left_primary_key_column=>:object_id, :right_primary_key=>:object_id, :right_primary_key_method=>:obj_id, :left_key=>:object_id, :right_key=>:foo_id, :eager_loader_key=>:object_id, :class=>@Foo
897
+ @foo = @Foo.create(:obj_id=>2)
898
+ @bar = @Bar.create(:obj_id=>2)
899
+ @Foo.db[:bars_foos].insert(2, 2)
900
+ end
901
+ after(:all) do
902
+ @db.drop_table(:bars_foos, :bars, :foos)
903
+ end
904
+
905
+ it "should have working regular association methods" do
906
+ @Bar.first.foo.should == @foo
907
+ @Foo.first.bars.should == [@bar]
908
+ @Foo.first.bar.should == @bar
909
+ @Foo.first.mtmbars.should == [@bar]
910
+ @Bar.first.mtmfoos.should == [@foo]
911
+ end
912
+
913
+ it "should have working eager loading methods" do
914
+ @Bar.eager(:foo).all.map{|o| [o, o.foo]}.should == [[@bar, @foo]]
915
+ @Foo.eager(:bars).all.map{|o| [o, o.bars]}.should == [[@foo, [@bar]]]
916
+ @Foo.eager(:bar).all.map{|o| [o, o.bar]}.should == [[@foo, @bar]]
917
+ @Foo.eager(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
918
+ @Bar.eager(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
919
+ end
920
+
921
+ it "should have working eager graphing methods" do
922
+ @Bar.eager_graph(:foo).all.map{|o| [o, o.foo]}.should == [[@bar, @foo]]
923
+ @Foo.eager_graph(:bars).all.map{|o| [o, o.bars]}.should == [[@foo, [@bar]]]
924
+ @Foo.eager_graph(:bar).all.map{|o| [o, o.bar]}.should == [[@foo, @bar]]
925
+ @Foo.eager_graph(:mtmbars).all.map{|o| [o, o.mtmbars]}.should == [[@foo, [@bar]]]
926
+ @Bar.eager_graph(:mtmfoos).all.map{|o| [o, o.mtmfoos]}.should == [[@bar, [@foo]]]
927
+ end
928
+
929
+ it "should have working modification methods" do
930
+ b = @Bar.create(:obj_id=>3)
931
+ f = @Foo.create(:obj_id=>3)
932
+
933
+ @bar.foo = f
934
+ @bar.obj_id.should == 3
935
+ @foo.bar = @bar
936
+ @bar.obj_id.should == 2
937
+
938
+ @foo.add_bar(b)
939
+ @foo.bars.sort_by{|x| x.obj_id}.should == [@bar, b]
940
+ @foo.remove_bar(b)
941
+ @foo.bars.should == [@bar]
942
+ @foo.remove_all_bars
943
+ @foo.bars.should == []
944
+
945
+ @bar.refresh.update(:obj_id=>2)
946
+ b.refresh.update(:obj_id=>3)
947
+ @foo.mtmbars.should == [@bar]
948
+ @foo.remove_all_mtmbars
949
+ @foo.mtmbars.should == []
950
+ @foo.add_mtmbar(b)
951
+ @foo.mtmbars.should == [b]
952
+ @foo.remove_mtmbar(b)
953
+ @foo.mtmbars.should == []
954
+
955
+ @bar.add_mtmfoo(f)
956
+ @bar.mtmfoos.should == [f]
957
+ @bar.remove_all_mtmfoos
958
+ @bar.mtmfoos.should == []
959
+ @bar.add_mtmfoo(f)
960
+ @bar.mtmfoos.should == [f]
961
+ @bar.remove_mtmfoo(f)
962
+ @bar.mtmfoos.should == []
963
+ end
964
+ end