sequel 4.3.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +34 -0
  3. data/README.rdoc +7 -7
  4. data/Rakefile +2 -2
  5. data/doc/active_record.rdoc +2 -2
  6. data/doc/association_basics.rdoc +21 -7
  7. data/doc/bin_sequel.rdoc +2 -2
  8. data/doc/cheat_sheet.rdoc +2 -1
  9. data/doc/dataset_basics.rdoc +1 -1
  10. data/doc/dataset_filtering.rdoc +1 -1
  11. data/doc/migration.rdoc +2 -2
  12. data/doc/object_model.rdoc +2 -2
  13. data/doc/opening_databases.rdoc +13 -1
  14. data/doc/querying.rdoc +9 -4
  15. data/doc/release_notes/4.4.0.txt +92 -0
  16. data/doc/schema_modification.rdoc +1 -1
  17. data/doc/security.rdoc +2 -2
  18. data/doc/sql.rdoc +3 -3
  19. data/doc/thread_safety.rdoc +1 -1
  20. data/doc/validations.rdoc +1 -1
  21. data/doc/virtual_rows.rdoc +1 -1
  22. data/lib/sequel/adapters/jdbc.rb +85 -19
  23. data/lib/sequel/adapters/jdbc/db2.rb +1 -1
  24. data/lib/sequel/adapters/jdbc/derby.rb +1 -1
  25. data/lib/sequel/adapters/jdbc/h2.rb +2 -2
  26. data/lib/sequel/adapters/jdbc/hsqldb.rb +7 -0
  27. data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
  28. data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
  29. data/lib/sequel/adapters/jdbc/postgresql.rb +34 -3
  30. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +57 -0
  31. data/lib/sequel/adapters/jdbc/sqlserver.rb +2 -2
  32. data/lib/sequel/adapters/oracle.rb +1 -1
  33. data/lib/sequel/adapters/shared/db2.rb +5 -0
  34. data/lib/sequel/adapters/shared/oracle.rb +41 -4
  35. data/lib/sequel/adapters/shared/sqlanywhere.rb +458 -0
  36. data/lib/sequel/adapters/sqlanywhere.rb +177 -0
  37. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +11 -3
  38. data/lib/sequel/core.rb +4 -4
  39. data/lib/sequel/database/connecting.rb +1 -1
  40. data/lib/sequel/database/query.rb +1 -1
  41. data/lib/sequel/database/schema_generator.rb +1 -1
  42. data/lib/sequel/database/schema_methods.rb +2 -2
  43. data/lib/sequel/dataset.rb +1 -1
  44. data/lib/sequel/dataset/actions.rb +2 -0
  45. data/lib/sequel/dataset/graph.rb +1 -1
  46. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  47. data/lib/sequel/dataset/query.rb +37 -16
  48. data/lib/sequel/extensions/constraint_validations.rb +1 -1
  49. data/lib/sequel/extensions/date_arithmetic.rb +2 -2
  50. data/lib/sequel/extensions/migration.rb +1 -1
  51. data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +5 -4
  52. data/lib/sequel/extensions/pg_array.rb +2 -2
  53. data/lib/sequel/extensions/pg_array_ops.rb +2 -2
  54. data/lib/sequel/extensions/pg_hstore.rb +2 -2
  55. data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
  56. data/lib/sequel/extensions/pg_json.rb +2 -2
  57. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  58. data/lib/sequel/extensions/pg_range.rb +2 -2
  59. data/lib/sequel/extensions/pg_range_ops.rb +2 -2
  60. data/lib/sequel/extensions/pg_row.rb +2 -2
  61. data/lib/sequel/extensions/pg_row_ops.rb +3 -3
  62. data/lib/sequel/model.rb +1 -1
  63. data/lib/sequel/model/associations.rb +106 -17
  64. data/lib/sequel/model/base.rb +23 -19
  65. data/lib/sequel/plugins/json_serializer.rb +1 -1
  66. data/lib/sequel/plugins/many_through_many.rb +14 -6
  67. data/lib/sequel/plugins/pg_array_associations.rb +28 -0
  68. data/lib/sequel/plugins/rcte_tree.rb +1 -1
  69. data/lib/sequel/plugins/serialization.rb +11 -0
  70. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  71. data/lib/sequel/plugins/table_select.rb +41 -0
  72. data/lib/sequel/plugins/tree.rb +1 -1
  73. data/lib/sequel/sql.rb +2 -2
  74. data/lib/sequel/version.rb +1 -1
  75. data/spec/adapters/oracle_spec.rb +22 -1
  76. data/spec/adapters/postgres_spec.rb +31 -48
  77. data/spec/adapters/sqlanywhere_spec.rb +170 -0
  78. data/spec/core/dataset_spec.rb +109 -0
  79. data/spec/core/object_graph_spec.rb +7 -0
  80. data/spec/extensions/constraint_validations_spec.rb +7 -0
  81. data/spec/extensions/core_refinements_spec.rb +1 -1
  82. data/spec/extensions/many_through_many_spec.rb +65 -0
  83. data/spec/extensions/pg_array_associations_spec.rb +44 -0
  84. data/spec/extensions/rcte_tree_spec.rb +3 -3
  85. data/spec/extensions/spec_helper.rb +1 -1
  86. data/spec/extensions/table_select_spec.rb +71 -0
  87. data/spec/integration/associations_test.rb +279 -7
  88. data/spec/integration/dataset_test.rb +13 -4
  89. data/spec/integration/schema_test.rb +12 -14
  90. data/spec/model/associations_spec.rb +472 -3
  91. data/spec/model/class_dataset_methods_spec.rb +1 -0
  92. data/spec/model/model_spec.rb +10 -0
  93. metadata +10 -2
@@ -211,7 +211,7 @@ describe Sequel::Model, "rcte_tree" do
211
211
  os = @ds.eager(:descendants=>2).all
212
212
  sqls = DB.sqls
213
213
  sqls.first.should == "SELECT * FROM nodes"
214
- sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\*, 0 AS x_level_x FROM nodes WHERE \(parent_id IN \([267], [267], [267]\)\) UNION ALL SELECT t\.x_root_x, nodes\.\*, \(t\.x_level_x \+ 1\) AS x_level_x FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\) WHERE \(t\.x_level_x < 1\)\) SELECT \* FROM t AS nodes/
214
+ sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\*, CAST\(0 AS integer\) AS x_level_x FROM nodes WHERE \(parent_id IN \([267], [267], [267]\)\) UNION ALL SELECT t\.x_root_x, nodes\.\*, \(t\.x_level_x \+ 1\) AS x_level_x FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\) WHERE \(t\.x_level_x < 1\)\) SELECT \* FROM t AS nodes/
215
215
  os.should == [@c.load(:id=>2, :parent_id=>1, :name=>'AA'), @c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>7, :parent_id=>1, :name=>'D')]
216
216
  os.map{|o| o.descendants}.should == [[@c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>9, :parent_id=>2, :name=>'E'), @c.load(:id=>3, :name=>'00', :parent_id=>6)],
217
217
  [@c.load(:id=>3, :name=>'00', :parent_id=>6)],
@@ -231,7 +231,7 @@ describe Sequel::Model, "rcte_tree" do
231
231
  os = @ds.eager(:ds=>2).all
232
232
  sqls = DB.sqls
233
233
  sqls.first.should == "SELECT * FROM nodes"
234
- sqls.last.should =~ /WITH cte AS \(SELECT pi AS kal, nodes\.\*, 0 AS lal FROM nodes WHERE \(pi IN \([267], [267], [267]\)\) UNION ALL SELECT cte\.kal, nodes\.\*, \(cte\.lal \+ 1\) AS lal FROM nodes INNER JOIN cte ON \(cte\.i = nodes\.pi\) WHERE \(cte\.lal < 1\)\) SELECT \* FROM cte/
234
+ sqls.last.should =~ /WITH cte AS \(SELECT pi AS kal, nodes\.\*, CAST\(0 AS integer\) AS lal FROM nodes WHERE \(pi IN \([267], [267], [267]\)\) UNION ALL SELECT cte\.kal, nodes\.\*, \(cte\.lal \+ 1\) AS lal FROM nodes INNER JOIN cte ON \(cte\.i = nodes\.pi\) WHERE \(cte\.lal < 1\)\) SELECT \* FROM cte/
235
235
  os.should == [@c.load(:i=>2, :pi=>1, :name=>'AA'), @c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>7, :pi=>1, :name=>'D')]
236
236
  os.map{|o| o.ds}.should == [[@c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>9, :pi=>2, :name=>'E'), @c.load(:i=>3, :name=>'00', :pi=>6)],
237
237
  [@c.load(:i=>3, :name=>'00', :pi=>6)],
@@ -366,7 +366,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
366
366
  os = @ds.eager(:descendants=>2).all
367
367
  sqls = DB.sqls
368
368
  sqls.first.should == "SELECT * FROM nodes"
369
- sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x_0, parent_id2 AS x_root_x_1, nodes\.\*, 0 AS x_level_x FROM nodes WHERE \(\(parent_id, parent_id2\) IN \(\([267], [378]\), \([267], [378]\), \([267], [378]\)\)\) UNION ALL SELECT t\.x_root_x_0, t\.x_root_x_1, nodes\.\*, \(t\.x_level_x \+ 1\) AS x_level_x FROM nodes INNER JOIN t ON \(\(t\.id = nodes\.parent_id\) AND \(t\.id2 = nodes\.parent_id2\)\) WHERE \(t\.x_level_x < 1\)\) SELECT \* FROM t AS nodes/
369
+ sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x_0, parent_id2 AS x_root_x_1, nodes\.\*, CAST\(0 AS integer\) AS x_level_x FROM nodes WHERE \(\(parent_id, parent_id2\) IN \(\([267], [378]\), \([267], [378]\), \([267], [378]\)\)\) UNION ALL SELECT t\.x_root_x_0, t\.x_root_x_1, nodes\.\*, \(t\.x_level_x \+ 1\) AS x_level_x FROM nodes INNER JOIN t ON \(\(t\.id = nodes\.parent_id\) AND \(t\.id2 = nodes\.parent_id2\)\) WHERE \(t\.x_level_x < 1\)\) SELECT \* FROM t AS nodes/
370
370
  os.should == [@c.load(:id=>2, :id2=>3, :parent_id=>1, :parent_id=>2, :name=>'AA'), @c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>7, :id2=>8, :parent_id=>1, :parent_id2=>2, :name=>'D')]
371
371
  os.map{|o| o.descendants}.should == [[@c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>9, :id2=>10, :parent_id=>2, :parent_id2=>3, :name=>'E'), @c.load(:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7)],
372
372
  [@c.load(:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7)],
@@ -31,7 +31,7 @@ rescue LoadError
31
31
  end
32
32
 
33
33
  Sequel.extension :meta_def
34
- Sequel.extension :core_refinements if RUBY_VERSION >= '2.0.0'
34
+ Sequel.extension :core_refinements if RUBY_VERSION >= '2.0.0' && respond_to?(:using)
35
35
 
36
36
  def skip_warn(s)
37
37
  warn "Skipping test of #{s}" if ENV["SKIPPED_TEST_WARN"]
@@ -0,0 +1,71 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::TableSelect" do
4
+ before do
5
+ @Album = Class.new(Sequel::Model(Sequel.mock[:albums]))
6
+ end
7
+
8
+ it "should add a table.* selection to existing dataset without explicit selection" do
9
+ @Album.plugin :table_select
10
+ @Album.dataset.sql.should == 'SELECT albums.* FROM albums'
11
+
12
+ @Album.dataset = :albs
13
+ @Album.dataset.sql.should == 'SELECT albs.* FROM albs'
14
+
15
+ @Album.dataset = Sequel.identifier(:albs)
16
+ @Album.dataset.sql.should == 'SELECT albs.* FROM albs'
17
+ end
18
+
19
+ it "should handle qualified tables" do
20
+ @Album.dataset = :s__albums
21
+ @Album.plugin :table_select
22
+ @Album.dataset.sql.should == 'SELECT s.albums.* FROM s.albums'
23
+
24
+ @Album.dataset = Sequel.qualify(:s2, :albums)
25
+ @Album.dataset.sql.should == 'SELECT s2.albums.* FROM s2.albums'
26
+ end
27
+
28
+ it "should handle aliases" do
29
+ @Album.dataset = :albums___a
30
+ @Album.plugin :table_select
31
+ @Album.dataset.sql.should == 'SELECT a.* FROM albums AS a'
32
+
33
+ @Album.dataset = Sequel.as(:albums, :b)
34
+ @Album.dataset.sql.should == 'SELECT b.* FROM albums AS b'
35
+
36
+ @Album.dataset = :s__albums___a
37
+ @Album.dataset.sql.should == 'SELECT a.* FROM s.albums AS a'
38
+
39
+ @Album.dataset = @Album.db[:albums].from_self
40
+ @Album.dataset.sql.should == 'SELECT t1.* FROM (SELECT * FROM albums) AS t1'
41
+
42
+ @Album.dataset = Sequel.as(@Album.db[:albums], :b)
43
+ @Album.dataset.sql.should == 'SELECT b.* FROM (SELECT * FROM albums) AS b'
44
+ end
45
+
46
+ it "should not add a table.* selection on existing dataset with explicit selection" do
47
+ @Album.dataset = @Album.dataset.select(:name)
48
+ @Album.plugin :table_select
49
+ @Album.dataset.sql.should == 'SELECT name FROM albums'
50
+
51
+ @Album.dataset = @Album.dataset.select(:name, :artist)
52
+ @Album.dataset.sql.should == 'SELECT name, artist FROM albums'
53
+ end
54
+
55
+ it "should not add a table.* selection on existing dataset with multiple tables" do
56
+ @Album.dataset = @Album.db.from(:a1, :a2)
57
+ @Album.plugin :table_select
58
+ @Album.dataset.sql.should == 'SELECT * FROM a1, a2'
59
+
60
+ @Album.dataset = @Album.db.from(:a1).cross_join(:a2)
61
+ @Album.dataset.sql.should == 'SELECT * FROM a1 CROSS JOIN a2'
62
+ end
63
+
64
+ it "works correctly when loaded on model without a dataset" do
65
+ c = Class.new(Sequel::Model)
66
+ c.plugin :table_select
67
+ sc = Class.new(c)
68
+ sc.dataset = :a
69
+ sc.dataset.sql.should == "SELECT a.* FROM a"
70
+ end
71
+ end
@@ -130,6 +130,7 @@ shared_examples_for "filtering/excluding by associations" do
130
130
 
131
131
  @Artist.filter(:albums=>@album).all.should == [@artist]
132
132
  @Artist.filter(:first_album=>@album).all.should == [@artist]
133
+ @Artist.filter(:tags=>@tag).all.should == [@artist] unless @no_many_through_many
133
134
  @Album.filter(:artist=>@artist).all.should == [@album]
134
135
  @Album.filter(:tags=>@tag).all.should == [@album]
135
136
  @Album.filter(:alias_tags=>@tag).all.should == [@album]
@@ -145,12 +146,59 @@ shared_examples_for "filtering/excluding by associations" do
145
146
 
146
147
  @Artist.exclude(:albums=>@album).all.should == [artist]
147
148
  @Artist.exclude(:first_album=>@album).all.should == [artist]
149
+ @Artist.exclude(:tags=>@tag).all.should == [artist] unless @no_many_through_many
148
150
  @Album.exclude(:artist=>@artist).all.should == [album]
149
151
  @Album.exclude(:tags=>@tag).all.should == [album]
150
152
  @Album.exclude(:alias_tags=>@tag).all.should == [album]
151
153
  @Tag.exclude(:albums=>@album).all.should == [tag]
152
154
  @Album.exclude(:artist=>@artist, :tags=>@tag).all.should == [album]
153
155
  end
156
+
157
+ specify "should work correctly when filtering by associations with conditions" do
158
+ @album.update(:artist => @artist)
159
+ @album.add_tag(@tag)
160
+
161
+ @Artist.filter(:a_albums=>@album).all.should == [@artist]
162
+ @Artist.filter(:first_a_album=>@album).all.should == [@artist]
163
+ @album.update(:name=>'Foo')
164
+ @Artist.filter(:a_albums=>@album).all.should == []
165
+ @Artist.filter(:first_a_album=>@album).all.should == []
166
+
167
+ @Album.filter(:a_artist=>@artist).all.should == [@album]
168
+ @artist.update(:name=>'Foo')
169
+ @Album.filter(:a_artist=>@artist).all.should == []
170
+
171
+ @Album.filter(:t_tags=>@tag).all.should == [@album]
172
+ @Album.filter(:alias_t_tags=>@tag).all.should == [@album]
173
+ @Artist.filter(:t_tags=>@tag).all.should == [@artist] unless @no_many_through_many
174
+ @tag.update(:name=>'Foo')
175
+ @Album.filter(:t_tags=>@tag).all.should == []
176
+ @Album.filter(:alias_t_tags=>@tag).all.should == []
177
+ @Artist.filter(:t_tags=>@tag).all.should == [] unless @no_many_through_many
178
+ end
179
+
180
+ specify "should work correctly when excluding by associations with conditions" do
181
+ @album.update(:artist => @artist)
182
+ @album.add_tag(@tag)
183
+
184
+ @Artist.exclude(:a_albums=>@album).all.should == []
185
+ @Artist.exclude(:first_a_album=>@album).all.should == []
186
+ @album.update(:name=>'Foo')
187
+ @Artist.exclude(:a_albums=>@album).all.should == [@artist]
188
+ @Artist.exclude(:first_a_album=>@album).all.should == [@artist]
189
+
190
+ @Album.exclude(:a_artist=>@artist).all.should == []
191
+ @artist.update(:name=>'Foo')
192
+ @Album.exclude(:a_artist=>@artist).all.should == [@album]
193
+
194
+ @Album.exclude(:t_tags=>@tag).all.should == []
195
+ @Album.exclude(:alias_t_tags=>@tag).all.should == []
196
+ @Artist.exclude(:t_tags=>@tag).all.should == [] unless @no_many_through_many
197
+ @tag.update(:name=>'Foo')
198
+ @Album.exclude(:t_tags=>@tag).all.should == [@album]
199
+ @Album.exclude(:alias_t_tags=>@tag).all.should == [@album]
200
+ @Artist.exclude(:t_tags=>@tag).all.should == [@artist] unless @no_many_through_many
201
+ end
154
202
 
155
203
  specify "should work correctly when filtering by multiple associations" do
156
204
  album, artist, tag = @pr.call
@@ -165,6 +213,7 @@ shared_examples_for "filtering/excluding by associations" do
165
213
  @Tag.filter(:albums=>[@album, album]).all.should == [@tag]
166
214
  @Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [@album]
167
215
  @artist.albums_dataset.filter(:tags=>[@tag, tag]).all.should == [@album]
216
+ @Artist.filter(:tags=>[@tag, tag]).all.should == [@artist] unless @no_many_through_many
168
217
 
169
218
  album.add_tag(tag)
170
219
 
@@ -175,6 +224,7 @@ shared_examples_for "filtering/excluding by associations" do
175
224
  @Album.filter(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
176
225
  @Tag.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
177
226
  @Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [@album]
227
+ @Artist.filter(:tags=>[@tag, tag]).all.should == [@artist] unless @no_many_through_many
178
228
 
179
229
  album.update(:artist => artist)
180
230
 
@@ -185,6 +235,7 @@ shared_examples_for "filtering/excluding by associations" do
185
235
  @Album.filter(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
186
236
  @Tag.filter(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
187
237
  @Album.filter(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
238
+ @Artist.filter(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@artist, artist] unless @no_many_through_many
188
239
  end
189
240
 
190
241
  specify "should work correctly when excluding by multiple associations" do
@@ -197,6 +248,7 @@ shared_examples_for "filtering/excluding by associations" do
197
248
  @Album.exclude(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
198
249
  @Tag.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@tag, tag]
199
250
  @Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
251
+ @Artist.exclude(:tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@artist, artist] unless @no_many_through_many
200
252
 
201
253
  @album.update(:artist => @artist)
202
254
  @album.add_tag(@tag)
@@ -208,6 +260,7 @@ shared_examples_for "filtering/excluding by associations" do
208
260
  @Album.exclude(:alias_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
209
261
  @Tag.exclude(:albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [tag]
210
262
  @Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [album]
263
+ @Artist.exclude(:tags=>[@tag, tag]).all.should == [artist] unless @no_many_through_many
211
264
 
212
265
  album.add_tag(tag)
213
266
 
@@ -218,6 +271,7 @@ shared_examples_for "filtering/excluding by associations" do
218
271
  @Album.exclude(:alias_tags=>[@tag, tag]).all.should == []
219
272
  @Tag.exclude(:albums=>[@album, album]).all.should == []
220
273
  @Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == [album]
274
+ @Artist.exclude(:tags=>[@tag, tag]).all.should == [artist] unless @no_many_through_many
221
275
 
222
276
  album.update(:artist => artist)
223
277
 
@@ -228,6 +282,90 @@ shared_examples_for "filtering/excluding by associations" do
228
282
  @Album.exclude(:alias_tags=>[@tag, tag]).all.should == []
229
283
  @Tag.exclude(:albums=>[@album, album]).all.should == []
230
284
  @Album.exclude(:artist=>[@artist, artist], :tags=>[@tag, tag]).all.should == []
285
+ @Artist.exclude(:tags=>[@tag, tag]).all.should == [] unless @no_many_through_many
286
+ end
287
+
288
+ specify "should work correctly when filtering associations with conditions with multiple objects" do
289
+ album, artist, tag = @pr.call
290
+ album.update(:name=>@album.name)
291
+ artist.update(:name=>@artist.name)
292
+ tag.update(:name=>@tag.name)
293
+
294
+ @album.update(:artist => @artist)
295
+ @album.add_tag(@tag)
296
+ album.update(:artist => @artist)
297
+ tag.add_album(@album)
298
+
299
+ @Artist.filter(:a_albums=>[@album, album]).all.should == [@artist]
300
+ @Artist.filter(:first_a_album=>[@album, album]).all.should == [@artist]
301
+ @album.update(:name=>'Foo')
302
+ @Artist.filter(:a_albums=>[@album, album]).all.should == [@artist]
303
+ @Artist.filter(:first_a_album=>[@album, album]).all.should == [@artist]
304
+ album.update(:name=>'Foo')
305
+ @Artist.filter(:a_albums=>[@album, album]).all.should == []
306
+ @Artist.filter(:first_a_album=>[@album, album]).all.should == []
307
+
308
+ album.update(:artist => nil)
309
+ artist.add_album(@album)
310
+ @Album.filter(:a_artist=>[@artist, artist]).all.should == [@album]
311
+ @artist.update(:name=>'Foo')
312
+ @Album.filter(:a_artist=>[@artist, artist]).all.should == [@album]
313
+ artist.update(:name=>'Foo')
314
+ @Album.filter(:a_artist=>[@artist, artist]).all.should == []
315
+
316
+ @Album.filter(:t_tags=>[@tag, tag]).all.should == [@album]
317
+ @Album.filter(:alias_t_tags=>[@tag, tag]).all.should == [@album]
318
+ @Artist.filter(:t_tags=>[@tag, tag]).all.should == [artist] unless @no_many_through_many
319
+ @tag.update(:name=>'Foo')
320
+ @Album.filter(:t_tags=>[@tag, tag]).all.should == [@album]
321
+ @Album.filter(:alias_t_tags=>[@tag, tag]).all.should == [@album]
322
+ @Artist.filter(:t_tags=>[@tag, tag]).all.should == [artist] unless @no_many_through_many
323
+ tag.update(:name=>'Foo')
324
+ @Album.filter(:t_tags=>[@tag, tag]).all.should == []
325
+ @Album.filter(:alias_t_tags=>[@tag, tag]).all.should == []
326
+ @Artist.filter(:t_tags=>[@tag, tag]).all.should == [] unless @no_many_through_many
327
+ end
328
+
329
+ specify "should work correctly when excluding associations with conditions with multiple objects" do
330
+ album, artist, tag = @pr.call
331
+ album.update(:name=>@album.name)
332
+ artist.update(:name=>@artist.name)
333
+ tag.update(:name=>@tag.name)
334
+
335
+ @album.update(:artist => @artist)
336
+ @album.add_tag(@tag)
337
+ album.update(:artist => @artist)
338
+ tag.add_album(@album)
339
+
340
+ artist.add_album(@album)
341
+ @Artist.exclude(:a_albums=>[@album, album]).all.should == []
342
+ @Artist.exclude(:first_a_album=>[@album, album]).all.should == []
343
+ @album.update(:name=>'Foo')
344
+ @Artist.exclude(:a_albums=>[@album, album]).all.should == [artist]
345
+ @Artist.exclude(:first_a_album=>[@album, album]).all.should == [artist]
346
+ album.update(:name=>'Foo')
347
+ @Artist.exclude(:a_albums=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
348
+ @Artist.exclude(:first_a_album=>[@album, album]).all.sort_by{|x| x.pk}.should == [@artist, artist]
349
+
350
+ @Album.exclude(:a_artist=>[@artist, artist]).all.should == []
351
+ album.update(:artist => nil)
352
+ @artist.update(:name=>'Foo')
353
+ @Album.exclude(:a_artist=>[@artist, artist]).all.should == [album]
354
+ artist.update(:name=>'Foo')
355
+ @Album.exclude(:a_artist=>[@artist, artist]).all.sort_by{|x| x.pk}.should == [@album, album]
356
+
357
+ @tag.add_album(album)
358
+ @Album.exclude(:t_tags=>[@tag, tag]).all.should == []
359
+ @Album.exclude(:alias_t_tags=>[@tag, tag]).all.should == []
360
+ @Artist.exclude(:t_tags=>[@tag, tag]).all.should == [@artist] unless @no_many_through_many
361
+ @tag.update(:name=>'Foo')
362
+ @Album.exclude(:t_tags=>[@tag, tag]).all.should == [album]
363
+ @Album.exclude(:alias_t_tags=>[@tag, tag]).all.should == [album]
364
+ @Artist.exclude(:t_tags=>[@tag, tag]).all.should == [@artist] unless @no_many_through_many
365
+ tag.update(:name=>'Foo')
366
+ @Album.exclude(:t_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
367
+ @Album.exclude(:alias_t_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@album, album]
368
+ @Artist.exclude(:t_tags=>[@tag, tag]).all.sort_by{|x| x.pk}.should == [@artist, artist] unless @no_many_through_many
231
369
  end
232
370
 
233
371
  specify "should work correctly when excluding by associations in regards to NULL values" do
@@ -239,6 +377,13 @@ shared_examples_for "filtering/excluding by associations" do
239
377
  @Tag.exclude(:albums=>@album).all.should == [@tag]
240
378
  @Album.exclude(:artist=>@artist, :tags=>@tag).all.should == [@album]
241
379
 
380
+ @Artist.exclude(:a_albums=>@album).all.should == [@artist]
381
+ @Artist.exclude(:first_a_album=>@album).all.should == [@artist]
382
+ @Album.exclude(:a_artist=>@artist).all.should == [@album]
383
+ @Album.exclude(:t_tags=>@tag).all.should == [@album]
384
+ @Album.exclude(:alias_t_tags=>@tag).all.should == [@album]
385
+ @Artist.exclude(:t_tags=>@tag).all.should == [@artist] unless @no_many_through_many
386
+
242
387
  @album.update(:artist => @artist)
243
388
  @artist.albums_dataset.exclude(:tags=>@tag).all.should == [@album]
244
389
  end
@@ -247,14 +392,22 @@ shared_examples_for "filtering/excluding by associations" do
247
392
  @ins.call
248
393
  @Album.exclude(:tags=>@tag).all.should == [@album]
249
394
  @Album.exclude(:alias_tags=>@tag).all.should == [@album]
395
+ @Album.exclude(:t_tags=>@tag).all.should == [@album]
396
+ @Album.exclude(:alias_t_tags=>@tag).all.should == [@album]
250
397
  @album.add_tag(@tag)
251
398
  @Album.filter(:tags=>@tag).all.should == [@album]
252
399
  @Album.filter(:alias_tags=>@tag).all.should == [@album]
400
+ @Album.filter(:t_tags=>@tag).all.should == [@album]
401
+ @Album.filter(:alias_t_tags=>@tag).all.should == [@album]
253
402
  album, tag = @pr.call.values_at(0, 2)
254
403
  @Album.exclude(:tags=>@tag).all.should == [album]
255
404
  @Album.exclude(:alias_tags=>@tag).all.should == [album]
405
+ @Album.exclude(:t_tags=>@tag).all.should == [album]
406
+ @Album.exclude(:alias_t_tags=>@tag).all.should == [album]
256
407
  @Album.exclude(:tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
257
408
  @Album.exclude(:alias_tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
409
+ @Album.exclude(:t_tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
410
+ @Album.exclude(:alias_t_tags=>tag).all.sort_by{|x| x.pk}.should == [@album, album]
258
411
  end
259
412
 
260
413
  specify "should work correctly when filtering by association datasets" do
@@ -282,6 +435,12 @@ shared_examples_for "filtering/excluding by associations" do
282
435
  @Tag.filter(:albums=>@Album).all.sort_by{|x| x.pk}.should == [@tag, tag]
283
436
  @Tag.filter(:albums=>@Album.filter(Array(Album.primary_key).map{|k| Sequel.qualify(Album.table_name, k)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [tag]
284
437
  @Tag.filter(:albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
438
+
439
+ unless @no_many_through_many
440
+ @Artist.filter(:tags=>@Tag).all.sort_by{|x| x.pk}.should == [@artist, artist]
441
+ @Artist.filter(:tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [artist]
442
+ @Artist.filter(:tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
443
+ end
285
444
  end
286
445
 
287
446
  specify "should work correctly when excluding by association datasets" do
@@ -294,6 +453,9 @@ shared_examples_for "filtering/excluding by associations" do
294
453
  @Artist.exclude(:albums=>@Album).all.sort_by{|x| x.pk}.should == []
295
454
  @Artist.exclude(:albums=>@Album.filter(Array(Album.primary_key).map{|k| Sequel.qualify(Album.table_name, k)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@artist]
296
455
  @Artist.exclude(:albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@artist, artist]
456
+ @Artist.exclude(:first_album=>@Album).all.sort_by{|x| x.pk}.should == []
457
+ @Artist.exclude(:first_album=>@Album.filter(Array(Album.primary_key).map{|k| Sequel.qualify(Album.table_name, k)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@artist]
458
+ @Artist.exclude(:first_album=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@artist, artist]
297
459
  @Album.exclude(:artist=>@Artist).all.sort_by{|x| x.pk}.should == []
298
460
  @Album.exclude(:artist=>@Artist.filter(Array(Artist.primary_key).map{|k| Sequel.qualify(Artist.table_name, k)}.zip(Array(artist.pk)))).all.sort_by{|x| x.pk}.should == [@album]
299
461
  @Album.exclude(:artist=>@Artist.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
@@ -306,7 +468,95 @@ shared_examples_for "filtering/excluding by associations" do
306
468
  @Tag.exclude(:albums=>@Album).all.sort_by{|x| x.pk}.should == []
307
469
  @Tag.exclude(:albums=>@Album.filter(Array(Album.primary_key).map{|k| Sequel.qualify(Album.table_name, k)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@tag]
308
470
  @Tag.exclude(:albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@tag, tag]
471
+
472
+ unless @no_many_through_many
473
+ @Artist.exclude(:tags=>@Tag).all.sort_by{|x| x.pk}.should == []
474
+ @Artist.exclude(:tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@artist]
475
+ @Artist.exclude(:tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@artist, artist]
476
+ end
477
+ end
478
+
479
+ specify "should work correctly when filtering by association datasets with conditions" do
480
+ album, artist, tag = @pr.call
481
+ @album.update(:artist => @artist)
482
+ @album.add_tag(@tag)
483
+ album.add_tag(tag)
484
+ album.update(:artist => artist)
485
+
486
+ @Artist.filter(:a_albums=>@Album).all.sort_by{|x| x.pk}.should == [@artist]
487
+ @Artist.filter(:first_a_album=>@Album).all.sort_by{|x| x.pk}.should == [@artist]
488
+ @Album.filter(:a_artist=>@Artist).all.sort_by{|x| x.pk}.should == [@album]
489
+ @Album.filter(:t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [@album]
490
+ @Album.filter(:alias_t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [@album]
491
+ @Artist.filter(:t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [@artist] unless @no_many_through_many
492
+
493
+ artist.update(:name=>@artist.name)
494
+ album.update(:name=>@album.name)
495
+ tag.update(:name=>@tag.name)
496
+
497
+ @Artist.filter(:a_albums=>@Album).all.sort_by{|x| x.pk}.should == [@artist, artist]
498
+ @Artist.filter(:first_a_album=>@Album).all.sort_by{|x| x.pk}.should == [@artist, artist]
499
+ @Album.filter(:a_artist=>@Artist).all.sort_by{|x| x.pk}.should == [@album, album]
500
+ @Album.filter(:t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [@album, album]
501
+ @Album.filter(:alias_t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [@album, album]
502
+ @Artist.filter(:t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [@artist, artist] unless @no_many_through_many
503
+
504
+ @Artist.filter(:a_albums=>@Album.filter(Array(Album.primary_key).map{|k| Sequel.qualify(Album.table_name, k)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [artist]
505
+ @Artist.filter(:first_a_album=>@Album.filter(Array(Album.primary_key).map{|k| Sequel.qualify(Album.table_name, k)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [artist]
506
+ @Album.filter(:a_artist=>@Artist.filter(Array(Artist.primary_key).map{|k| Sequel.qualify(Artist.table_name, k)}.zip(Array(artist.pk)))).all.sort_by{|x| x.pk}.should == [album]
507
+ @Album.filter(:t_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
508
+ @Album.filter(:alias_t_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
509
+ @Artist.filter(:t_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [artist] unless @no_many_through_many
510
+
511
+ @Artist.filter(:a_albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
512
+ @Artist.filter(:first_a_album=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
513
+ @Album.filter(:a_artist=>@Artist.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
514
+ @Album.filter(:t_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [album]
515
+ @Album.filter(:t_tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
516
+ @Album.filter(:alias_t_tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == []
517
+ @Artist.filter(:t_tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == [] unless @no_many_through_many
309
518
  end
519
+
520
+ specify "should work correctly when excluding by association datasets with conditions" do
521
+ album, artist, tag = @pr.call
522
+ @album.update(:artist => @artist)
523
+ @album.add_tag(@tag)
524
+ album.add_tag(tag)
525
+ album.update(:artist => artist)
526
+
527
+ @Artist.exclude(:a_albums=>@Album).all.sort_by{|x| x.pk}.should == [artist]
528
+ @Artist.exclude(:first_a_album=>@Album).all.sort_by{|x| x.pk}.should == [artist]
529
+ @Album.exclude(:a_artist=>@Artist).all.sort_by{|x| x.pk}.should == [album]
530
+ @Album.exclude(:t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [album]
531
+ @Album.exclude(:alias_t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [album]
532
+ @Artist.exclude(:t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [artist] unless @no_many_through_many
533
+
534
+ artist.update(:name=>@artist.name)
535
+ album.update(:name=>@album.name)
536
+ tag.update(:name=>@tag.name)
537
+
538
+ @Artist.exclude(:a_albums=>@Album).all.sort_by{|x| x.pk}.should == []
539
+ @Artist.exclude(:first_a_album=>@Album).all.sort_by{|x| x.pk}.should == []
540
+ @Album.exclude(:a_artist=>@Artist).all.sort_by{|x| x.pk}.should == []
541
+ @Album.exclude(:t_tags=>@Tag).all.sort_by{|x| x.pk}.should == []
542
+ @Album.exclude(:alias_t_tags=>@Tag).all.sort_by{|x| x.pk}.should == []
543
+ @Artist.exclude(:t_tags=>@Tag).all.sort_by{|x| x.pk}.should == [] unless @no_many_through_many
544
+
545
+ @Artist.exclude(:a_albums=>@Album.filter(Array(Album.primary_key).map{|k| Sequel.qualify(Album.table_name, k)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@artist]
546
+ @Artist.exclude(:first_a_album=>@Album.filter(Array(Album.primary_key).map{|k| Sequel.qualify(Album.table_name, k)}.zip(Array(album.pk)))).all.sort_by{|x| x.pk}.should == [@artist]
547
+ @Album.exclude(:a_artist=>@Artist.filter(Array(Artist.primary_key).map{|k| Sequel.qualify(Artist.table_name, k)}.zip(Array(artist.pk)))).all.sort_by{|x| x.pk}.should == [@album]
548
+ @Album.exclude(:t_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@album]
549
+ @Album.exclude(:alias_t_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@album]
550
+ @Artist.exclude(:t_tags=>@Tag.filter(Array(Tag.primary_key).map{|k| Sequel.qualify(Tag.table_name, k)}.zip(Array(tag.pk)))).all.sort_by{|x| x.pk}.should == [@artist] unless @no_many_through_many
551
+
552
+ @Artist.exclude(:a_albums=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@artist, artist]
553
+ @Artist.exclude(:first_a_album=>@Album.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@artist, artist]
554
+ @Album.exclude(:a_artist=>@Artist.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
555
+ @Album.exclude(:t_tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
556
+ @Album.exclude(:alias_t_tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@album, album]
557
+ @Artist.exclude(:t_tags=>@Tag.filter(1=>0)).all.sort_by{|x| x.pk}.should == [@artist, artist] unless @no_many_through_many
558
+ end
559
+
310
560
  end
311
561
 
312
562
  shared_examples_for "basic regular and composite key associations" do
@@ -588,29 +838,35 @@ describe "Sequel::Model Simple Associations" do
588
838
  class ::Artist < Sequel::Model(@db)
589
839
  plugin :dataset_associations
590
840
  one_to_many :albums, :order=>:name
591
- one_to_one :first_album, :class=>:Album, :order=>:name
592
- one_to_one :second_album, :class=>:Album, :order=>:name, :limit=>[nil, 1]
841
+ one_to_one :first_album, :clone=>:albums
842
+ one_to_one :second_album, :clone=>:albums, :limit=>[nil, 1]
593
843
  one_to_one :last_album, :class=>:Album, :order=>Sequel.desc(:name)
594
- one_to_many :first_two_albums, :class=>:Album, :order=>:name, :limit=>2
595
- one_to_many :second_two_albums, :class=>:Album, :order=>:name, :limit=>[2, 1]
596
- one_to_many :not_first_albums, :class=>:Album, :order=>:name, :limit=>[nil, 1]
844
+ one_to_many :first_two_albums, :clone=>:albums, :limit=>2
845
+ one_to_many :second_two_albums, :clone=>:albums, :limit=>[2, 1]
846
+ one_to_many :not_first_albums, :clone=>:albums, :limit=>[nil, 1]
597
847
  one_to_many :last_two_albums, :class=>:Album, :order=>Sequel.desc(:name), :limit=>2
848
+ one_to_many :a_albums, :clone=>:albums, :conditions=>{:name=>'Al'}
849
+ one_to_one :first_a_album, :clone=>:a_albums
598
850
  plugin :many_through_many
599
851
  many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]]
600
852
  many_through_many :first_two_tags, :clone=>:tags, :order=>:tags__name, :limit=>2
601
853
  many_through_many :second_two_tags, :clone=>:tags, :order=>:tags__name, :limit=>[2, 1]
602
854
  many_through_many :not_first_tags, :clone=>:tags, :order=>:tags__name, :limit=>[nil, 1]
603
855
  many_through_many :last_two_tags, :clone=>:tags, :order=>Sequel.desc(:tags__name), :limit=>2
856
+ many_through_many :t_tags, :clone=>:tags, :conditions=>{:tags__name=>'T'}
604
857
  end
605
858
  class ::Album < Sequel::Model(@db)
606
859
  plugin :dataset_associations
607
860
  many_to_one :artist, :reciprocal=>nil
861
+ many_to_one :a_artist, :clone=>:artist, :conditions=>{:name=>'Ar'}, :key=>:artist_id
608
862
  many_to_many :tags, :right_key=>:tag_id
609
863
  many_to_many :alias_tags, :clone=>:tags, :join_table=>:albums_tags___at
610
864
  many_to_many :first_two_tags, :clone=>:tags, :order=>:name, :limit=>2
611
865
  many_to_many :second_two_tags, :clone=>:tags, :order=>:name, :limit=>[2, 1]
612
866
  many_to_many :not_first_tags, :clone=>:tags, :order=>:name, :limit=>[nil, 1]
613
867
  many_to_many :last_two_tags, :clone=>:tags, :order=>Sequel.desc(:name), :limit=>2
868
+ many_to_many :t_tags, :clone=>:tags, :conditions=>{:name=>'T'}
869
+ many_to_many :alias_t_tags, :clone=>:t_tags, :join_table=>:albums_tags___at
614
870
  end
615
871
  class ::Tag < Sequel::Model(@db)
616
872
  plugin :dataset_associations
@@ -801,24 +1057,30 @@ describe "Sequel::Model Composite Key Associations" do
801
1057
  one_to_many :second_two_albums, :clone=>:albums, :order=>:name, :limit=>[2, 1]
802
1058
  one_to_many :not_first_albums, :clone=>:albums, :order=>:name, :limit=>[nil, 1]
803
1059
  one_to_many :last_two_albums, :clone=>:albums, :order=>Sequel.desc(:name), :limit=>2
1060
+ one_to_many :a_albums, :clone=>:albums do |ds| ds.where(:name=>'Al') end
1061
+ one_to_one :first_a_album, :clone=>:a_albums
804
1062
  plugin :many_through_many
805
1063
  many_through_many :tags, [[:albums, [:artist_id1, :artist_id2], [:id1, :id2]], [:albums_tags, [:album_id1, :album_id2], [:tag_id1, :tag_id2]]]
806
1064
  many_through_many :first_two_tags, :clone=>:tags, :order=>:tags__name, :limit=>2
807
1065
  many_through_many :second_two_tags, :clone=>:tags, :order=>:tags__name, :limit=>[2, 1]
808
1066
  many_through_many :not_first_tags, :clone=>:tags, :order=>:tags__name, :limit=>[nil, 1]
809
1067
  many_through_many :last_two_tags, :clone=>:tags, :order=>Sequel.desc(:tags__name), :limit=>2
1068
+ many_through_many :t_tags, :clone=>:tags do |ds| ds.where(:tags__name=>'T') end
810
1069
  end
811
1070
  class ::Album < Sequel::Model(@db)
812
1071
  plugin :dataset_associations
813
1072
  set_primary_key [:id1, :id2]
814
1073
  unrestrict_primary_key
815
1074
  many_to_one :artist, :key=>[:artist_id1, :artist_id2], :reciprocal=>nil
1075
+ many_to_one(:a_artist, :clone=>:artist){|ds| ds.where(:name=>'Ar')}
816
1076
  many_to_many :tags, :left_key=>[:album_id1, :album_id2], :right_key=>[:tag_id1, :tag_id2]
817
1077
  many_to_many :alias_tags, :clone=>:tags, :join_table=>:albums_tags___at
818
1078
  many_to_many :first_two_tags, :clone=>:tags, :order=>:name, :limit=>2
819
1079
  many_to_many :second_two_tags, :clone=>:tags, :order=>:name, :limit=>[2, 1]
820
1080
  many_to_many :not_first_tags, :clone=>:tags, :order=>:name, :limit=>[nil, 1]
821
1081
  many_to_many :last_two_tags, :clone=>:tags, :order=>Sequel.desc(:name), :limit=>2
1082
+ many_to_many :t_tags, :clone=>:tags do |ds| ds.where(:name=>'T') end
1083
+ many_to_many :alias_t_tags, :clone=>:t_tags, :join_table=>:albums_tags___at
822
1084
  end
823
1085
  class ::Tag < Sequel::Model(@db)
824
1086
  plugin :dataset_associations
@@ -911,18 +1173,23 @@ describe "Sequel::Model pg_array_to_many" do
911
1173
  class ::Artist < Sequel::Model(@db)
912
1174
  plugin :dataset_associations
913
1175
  one_to_many :albums, :order=>:name
914
- one_to_one :first_album, :class=>:Album, :order=>:name
1176
+ one_to_one :first_album, :clone=>:albums
1177
+ one_to_many :a_albums, :clone=>:albums do |ds| ds.where(:name=>'Al') end
1178
+ one_to_one :first_a_album, :clone=>:a_albums
915
1179
  end
916
1180
  class ::Album < Sequel::Model(@db)
917
1181
  plugin :dataset_associations
918
1182
  plugin :pg_array_associations
919
1183
  many_to_one :artist, :reciprocal=>nil
1184
+ many_to_one :a_artist, :clone=>:artist, :key=>:artist_id do |ds| ds.where(:name=>'Ar') end
920
1185
  pg_array_to_many :tags, :key=>:tag_ids, :save_after_modify=>true
921
1186
  pg_array_to_many :alias_tags, :clone=>:tags
922
1187
  pg_array_to_many :first_two_tags, :clone=>:tags, :order=>:name, :limit=>2
923
1188
  pg_array_to_many :second_two_tags, :clone=>:tags, :order=>:name, :limit=>[2, 1]
924
1189
  pg_array_to_many :not_first_tags, :clone=>:tags, :order=>:name, :limit=>[nil, 1]
925
1190
  pg_array_to_many :last_two_tags, :clone=>:tags, :order=>Sequel.desc(:name), :limit=>2
1191
+ pg_array_to_many :t_tags, :clone=>:tags do |ds| ds.where(:tags__name=>'T') end
1192
+ pg_array_to_many :alias_t_tags, :clone=>:t_tags
926
1193
  end
927
1194
  class ::Tag < Sequel::Model(@db)
928
1195
  plugin :dataset_associations
@@ -987,22 +1254,27 @@ describe "Sequel::Model many_to_pg_array" do
987
1254
  plugin :dataset_associations
988
1255
  one_to_many :albums, :order=>:name
989
1256
  one_to_one :first_album, :class=>:Album, :order=>:name
1257
+ one_to_many :a_albums, :clone=>:albums do |ds| ds.where(:name=>'Al') end
1258
+ one_to_one :first_a_album, :clone=>:a_albums
990
1259
  end
991
1260
  class ::Album < Sequel::Model(@db)
992
1261
  plugin :dataset_associations
993
1262
  plugin :pg_array_associations
994
1263
  many_to_one :artist, :reciprocal=>nil
1264
+ many_to_one :a_artist, :clone=>:artist, :key=>:artist_id do |ds| ds.where(:name=>'Ar') end
995
1265
  many_to_pg_array :tags
996
1266
  many_to_pg_array :alias_tags, :clone=>:tags
997
1267
  many_to_pg_array :first_two_tags, :clone=>:tags, :order=>:name, :limit=>2
998
1268
  many_to_pg_array :second_two_tags, :clone=>:tags, :order=>:name, :limit=>[2, 1]
999
1269
  many_to_pg_array :not_first_tags, :clone=>:tags, :order=>:name, :limit=>[nil, 1]
1000
1270
  many_to_pg_array :last_two_tags, :clone=>:tags, :order=>Sequel.desc(:name), :limit=>2
1271
+ many_to_pg_array :t_tags, :clone=>:tags do |ds| ds.where(:tags__name=>'T') end
1272
+ many_to_pg_array :alias_t_tags, :clone=>:t_tags
1001
1273
  end
1002
1274
  class ::Tag < Sequel::Model(@db)
1003
1275
  plugin :dataset_associations
1004
1276
  plugin :pg_array_associations
1005
- pg_array_to_many :albums
1277
+ pg_array_to_many :albums, :save_after_modify=>true
1006
1278
  end
1007
1279
  @album = Album.create(:name=>'Al')
1008
1280
  @artist = Artist.create(:name=>'Ar')