sequel 4.3.0 → 4.4.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 (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')