sequel 3.31.0 → 3.32.0

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 (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