sequel 3.33.0 → 3.34.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.
- data/CHANGELOG +140 -0
- data/Rakefile +7 -0
- data/bin/sequel +22 -2
- data/doc/dataset_basics.rdoc +1 -1
- data/doc/mass_assignment.rdoc +3 -1
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +23 -3
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/schema_modification.rdoc +18 -2
- data/doc/virtual_rows.rdoc +49 -0
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/ibmdb.rb +9 -4
- data/lib/sequel/adapters/jdbc.rb +9 -4
- data/lib/sequel/adapters/jdbc/h2.rb +8 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +19 -0
- data/lib/sequel/adapters/mock.rb +24 -3
- data/lib/sequel/adapters/mysql.rb +29 -50
- data/lib/sequel/adapters/mysql2.rb +13 -28
- data/lib/sequel/adapters/oracle.rb +8 -2
- data/lib/sequel/adapters/postgres.rb +115 -20
- data/lib/sequel/adapters/shared/db2.rb +1 -1
- data/lib/sequel/adapters/shared/mssql.rb +14 -3
- data/lib/sequel/adapters/shared/mysql.rb +59 -11
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +127 -30
- data/lib/sequel/adapters/shared/sqlite.rb +55 -38
- data/lib/sequel/adapters/sqlite.rb +9 -3
- data/lib/sequel/adapters/swift.rb +2 -2
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +10 -0
- data/lib/sequel/ast_transformer.rb +4 -0
- data/lib/sequel/connection_pool.rb +8 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +17 -0
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +14 -0
- data/lib/sequel/core.rb +24 -3
- data/lib/sequel/database/connecting.rb +24 -14
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +16 -25
- data/lib/sequel/database/query.rb +20 -2
- data/lib/sequel/database/schema_generator.rb +2 -2
- data/lib/sequel/database/schema_methods.rb +120 -23
- data/lib/sequel/dataset/actions.rb +91 -18
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/prepared_statements.rb +6 -2
- data/lib/sequel/dataset/sql.rb +68 -51
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +18 -13
- data/lib/sequel/extensions/migration.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +174 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +227 -31
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- data/lib/sequel/extensions/to_dot.rb +1 -1
- data/lib/sequel/model.rb +11 -2
- data/lib/sequel/model/associations.rb +35 -7
- data/lib/sequel/model/base.rb +159 -36
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/composition.rb +1 -1
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +11 -3
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +4 -3
- data/lib/sequel/plugins/prepared_statements.rb +3 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +5 -1
- data/lib/sequel/plugins/schema.rb +7 -2
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/sql.rb +417 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +12 -15
- data/spec/adapters/mysql_spec.rb +81 -23
- data/spec/adapters/postgres_spec.rb +444 -77
- data/spec/adapters/spec_helper.rb +2 -0
- data/spec/adapters/sqlite_spec.rb +8 -8
- data/spec/core/connection_pool_spec.rb +85 -0
- data/spec/core/database_spec.rb +29 -5
- data/spec/core/dataset_spec.rb +171 -3
- data/spec/core/expression_filters_spec.rb +364 -0
- data/spec/core/mock_adapter_spec.rb +17 -3
- data/spec/core/schema_spec.rb +133 -0
- data/spec/extensions/association_dependencies_spec.rb +13 -13
- data/spec/extensions/caching_spec.rb +26 -3
- data/spec/extensions/class_table_inheritance_spec.rb +2 -2
- data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +23 -94
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +5 -2
- data/spec/extensions/identity_map_spec.rb +17 -0
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/lazy_attributes_spec.rb +2 -2
- data/spec/extensions/list_spec.rb +4 -4
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +6 -2
- data/spec/extensions/nested_attributes_spec.rb +20 -0
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +2 -2
- data/spec/extensions/pg_array_ops_spec.rb +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +64 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -0
- data/spec/extensions/prepared_statements_spec.rb +4 -0
- data/spec/extensions/pretty_table_spec.rb +6 -0
- data/spec/extensions/query_literals_spec.rb +168 -0
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +231 -11
- data/spec/extensions/schema_spec.rb +14 -2
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/sharding_spec.rb +6 -6
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +2 -1
- data/spec/extensions/sql_expr_spec.rb +28 -19
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/typecast_on_load_spec.rb +9 -1
- data/spec/integration/associations_test.rb +6 -6
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +89 -26
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +3 -3
- data/spec/integration/plugin_test.rb +85 -22
- data/spec/integration/prepared_statement_test.rb +28 -8
- data/spec/integration/schema_test.rb +78 -7
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +4 -6
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/associations_spec.rb +94 -8
- data/spec/model/base_spec.rb +4 -4
- data/spec/model/hooks_spec.rb +2 -2
- data/spec/model/model_spec.rb +19 -7
- data/spec/model/record_spec.rb +135 -58
- data/spec/model/spec_helper.rb +1 -0
- metadata +35 -7
|
@@ -21,55 +21,55 @@ describe "AssociationDependencies plugin" do
|
|
|
21
21
|
specify "should allow destroying associated many_to_one associated object" do
|
|
22
22
|
@Album.add_association_dependencies :artist=>:destroy
|
|
23
23
|
@Album.load(:id=>1, :name=>'Al', :artist_id=>2).destroy
|
|
24
|
-
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE
|
|
24
|
+
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE id = 1', 'SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1', 'DELETE FROM artists WHERE id = 2']
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
specify "should allow deleting associated many_to_one associated object" do
|
|
28
28
|
@Album.add_association_dependencies :artist=>:delete
|
|
29
29
|
@Album.load(:id=>1, :name=>'Al', :artist_id=>2).destroy
|
|
30
|
-
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE
|
|
30
|
+
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE id = 1', 'DELETE FROM artists WHERE (artists.id = 2)']
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
specify "should allow destroying associated one_to_one associated object" do
|
|
34
34
|
@Artist.add_association_dependencies :first_album=>:destroy
|
|
35
35
|
@Artist.load(:id=>2, :name=>'Ar').destroy
|
|
36
|
-
MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE ((albums.artist_id = 2) AND (position = 1)) LIMIT 1', 'DELETE FROM albums WHERE
|
|
36
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE ((albums.artist_id = 2) AND (position = 1)) LIMIT 1', 'DELETE FROM albums WHERE id = 1', 'DELETE FROM artists WHERE id = 2']
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
specify "should allow deleting associated one_to_one associated object" do
|
|
40
40
|
@Artist.add_association_dependencies :first_album=>:delete
|
|
41
41
|
@Artist.load(:id=>2, :name=>'Ar').destroy
|
|
42
|
-
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE ((albums.artist_id = 2) AND (position = 1))', 'DELETE FROM artists WHERE
|
|
42
|
+
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE ((albums.artist_id = 2) AND (position = 1))', 'DELETE FROM artists WHERE id = 2']
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
specify "should allow destroying associated one_to_many objects" do
|
|
46
46
|
@Artist.add_association_dependencies :albums=>:destroy
|
|
47
47
|
@Artist.load(:id=>2, :name=>'Ar').destroy
|
|
48
|
-
MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE (albums.artist_id = 2)', 'DELETE FROM albums WHERE
|
|
48
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE (albums.artist_id = 2)', 'DELETE FROM albums WHERE id = 1', 'DELETE FROM artists WHERE id = 2']
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
specify "should allow deleting associated one_to_many objects" do
|
|
52
52
|
@Artist.add_association_dependencies :albums=>:delete
|
|
53
53
|
@Artist.load(:id=>2, :name=>'Ar').destroy
|
|
54
|
-
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE (albums.artist_id = 2)', 'DELETE FROM artists WHERE
|
|
54
|
+
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE (albums.artist_id = 2)', 'DELETE FROM artists WHERE id = 2']
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
specify "should allow nullifying associated one_to_one objects" do
|
|
58
58
|
@Artist.add_association_dependencies :first_album=>:nullify
|
|
59
59
|
@Artist.load(:id=>2, :name=>'Ar').destroy
|
|
60
|
-
MODEL_DB.sqls.should == ['UPDATE albums SET artist_id = NULL WHERE ((artist_id = 2) AND (position = 1))', 'DELETE FROM artists WHERE
|
|
60
|
+
MODEL_DB.sqls.should == ['UPDATE albums SET artist_id = NULL WHERE ((artist_id = 2) AND (position = 1))', 'DELETE FROM artists WHERE id = 2']
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
specify "should allow nullifying associated one_to_many objects" do
|
|
64
64
|
@Artist.add_association_dependencies :albums=>:nullify
|
|
65
65
|
@Artist.load(:id=>2, :name=>'Ar').destroy
|
|
66
|
-
MODEL_DB.sqls.should == ['UPDATE albums SET artist_id = NULL WHERE (artist_id = 2)', 'DELETE FROM artists WHERE
|
|
66
|
+
MODEL_DB.sqls.should == ['UPDATE albums SET artist_id = NULL WHERE (artist_id = 2)', 'DELETE FROM artists WHERE id = 2']
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
specify "should allow nullifying associated many_to_many associations" do
|
|
70
70
|
@Artist.add_association_dependencies :other_artists=>:nullify
|
|
71
71
|
@Artist.load(:id=>2, :name=>'Ar').destroy
|
|
72
|
-
MODEL_DB.sqls.should == ['DELETE FROM aoa WHERE (l = 2)', 'DELETE FROM artists WHERE
|
|
72
|
+
MODEL_DB.sqls.should == ['DELETE FROM aoa WHERE (l = 2)', 'DELETE FROM artists WHERE id = 2']
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
specify "should raise an error if attempting to nullify a many_to_one association" do
|
|
@@ -97,21 +97,21 @@ describe "AssociationDependencies plugin" do
|
|
|
97
97
|
specify "should allow specifying association dependencies in the plugin call" do
|
|
98
98
|
@Album.plugin :association_dependencies, :artist=>:destroy
|
|
99
99
|
@Album.load(:id=>1, :name=>'Al', :artist_id=>2).destroy
|
|
100
|
-
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE
|
|
100
|
+
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE id = 1', 'SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1', 'DELETE FROM artists WHERE id = 2']
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
specify "should work with subclasses" do
|
|
104
104
|
c = Class.new(@Album)
|
|
105
105
|
c.add_association_dependencies :artist=>:destroy
|
|
106
106
|
c.load(:id=>1, :name=>'Al', :artist_id=>2).destroy
|
|
107
|
-
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE
|
|
107
|
+
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE id = 1', 'SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1', 'DELETE FROM artists WHERE id = 2']
|
|
108
108
|
|
|
109
109
|
@Album.load(:id=>1, :name=>'Al', :artist_id=>2).destroy
|
|
110
|
-
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE
|
|
110
|
+
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE id = 1']
|
|
111
111
|
|
|
112
112
|
@Album.add_association_dependencies :artist=>:destroy
|
|
113
113
|
c2 = Class.new(@Album)
|
|
114
114
|
c2.load(:id=>1, :name=>'Al', :artist_id=>2).destroy
|
|
115
|
-
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE
|
|
115
|
+
MODEL_DB.sqls.should == ['DELETE FROM albums WHERE id = 1', 'SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1', 'DELETE FROM artists WHERE id = 2']
|
|
116
116
|
end
|
|
117
117
|
end
|
|
@@ -82,7 +82,7 @@ describe Sequel::Model, "caching" do
|
|
|
82
82
|
Class.new(@c).cache_ttl.should == 1234
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
it "should generate a cache key appropriate to the class" do
|
|
85
|
+
it "should generate a cache key appropriate to the class via the Model#cache_key" do
|
|
86
86
|
m = @c.new
|
|
87
87
|
m.values[:id] = 1
|
|
88
88
|
m.cache_key.should == "#{m.class}:1"
|
|
@@ -114,6 +114,11 @@ describe Sequel::Model, "caching" do
|
|
|
114
114
|
m.values[:b] = 789
|
|
115
115
|
m.cache_key.should == "#{m.class}:123,789,456"
|
|
116
116
|
end
|
|
117
|
+
|
|
118
|
+
it "should generate a cache key via the Model.cache_key method" do
|
|
119
|
+
@c.cache_key(1).should == "#{@c}:1"
|
|
120
|
+
@c.cache_key([1, 2]).should == "#{@c}:1,2"
|
|
121
|
+
end
|
|
117
122
|
|
|
118
123
|
it "should raise error if attempting to generate cache_key and primary key value is null" do
|
|
119
124
|
m = @c.new
|
|
@@ -156,6 +161,11 @@ describe Sequel::Model, "caching" do
|
|
|
156
161
|
m2.should == m
|
|
157
162
|
m2.values.should == {:name=>"sharon", :id=>1}
|
|
158
163
|
end
|
|
164
|
+
|
|
165
|
+
it "should handle lookups by nil primary keys" do
|
|
166
|
+
@c[nil].should == nil
|
|
167
|
+
@c.db.sqls.should == []
|
|
168
|
+
end
|
|
159
169
|
|
|
160
170
|
it "should delete the cache when writing to the database" do
|
|
161
171
|
m = @c[1]
|
|
@@ -178,13 +188,13 @@ describe Sequel::Model, "caching" do
|
|
|
178
188
|
@cache[m.cache_key].should == m
|
|
179
189
|
m.delete
|
|
180
190
|
@cache.has_key?(m.cache_key).should be_false
|
|
181
|
-
@c.db.sqls.should == ["SELECT * FROM items WHERE id = 1", "DELETE FROM items WHERE
|
|
191
|
+
@c.db.sqls.should == ["SELECT * FROM items WHERE id = 1", "DELETE FROM items WHERE id = 1"]
|
|
182
192
|
|
|
183
193
|
m = @c2[1]
|
|
184
194
|
@cache[m.cache_key].should == m
|
|
185
195
|
m.delete
|
|
186
196
|
@cache.has_key?(m.cache_key).should be_false
|
|
187
|
-
@c.db.sqls.should == ["SELECT * FROM items WHERE id = 1", "DELETE FROM items WHERE
|
|
197
|
+
@c.db.sqls.should == ["SELECT * FROM items WHERE id = 1", "DELETE FROM items WHERE id = 1"]
|
|
188
198
|
end
|
|
189
199
|
|
|
190
200
|
it "should support #[] as a shortcut to #find with hash" do
|
|
@@ -220,4 +230,17 @@ describe Sequel::Model, "caching" do
|
|
|
220
230
|
it "should rescue an exception if cache_store is memcached and ignore_exception is enabled" do
|
|
221
231
|
@c4[1].values.should == {:name => 'sharon', :id => 1}
|
|
222
232
|
end
|
|
233
|
+
|
|
234
|
+
it "should support Model.cache_get_pk for getting a value from the cache by primary key" do
|
|
235
|
+
@c.cache_get_pk(1).should == nil
|
|
236
|
+
m = @c[1]
|
|
237
|
+
@c.cache_get_pk(1).should == m
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it "should support Model.cache_delete_pk for removing a value from the cache by primary key" do
|
|
241
|
+
@c[1]
|
|
242
|
+
@c.cache_get_pk(1).should_not == nil
|
|
243
|
+
@c.cache_delete_pk(1).should == nil
|
|
244
|
+
@c.cache_get_pk(1).should == nil
|
|
245
|
+
end
|
|
223
246
|
end
|
|
@@ -130,10 +130,10 @@ describe "class_table_inheritance plugin" do
|
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
it "should lazily load attributes for columns in subclass tables" do
|
|
133
|
-
Manager.dataset._fetch = {:id=>1, :name=>'J', :kind=>'Executive', :num_staff=>2}
|
|
133
|
+
Manager.instance_dataset._fetch = Manager.dataset._fetch = {:id=>1, :name=>'J', :kind=>'Executive', :num_staff=>2}
|
|
134
134
|
m = Manager[1]
|
|
135
135
|
@db.sqls.should == ['SELECT * FROM employees INNER JOIN managers USING (id) WHERE (id = 1) LIMIT 1']
|
|
136
|
-
Executive.dataset._fetch = {:num_managers=>3}
|
|
136
|
+
Executive.instance_dataset._fetch = Executive.dataset._fetch = {:num_managers=>3}
|
|
137
137
|
m.num_managers.should == 3
|
|
138
138
|
@db.sqls.should == ['SELECT num_managers FROM employees INNER JOIN managers USING (id) INNER JOIN executives USING (id) WHERE (id = 1) LIMIT 1']
|
|
139
139
|
m.values.should == {:id=>1, :name=>'J', :kind=>'Executive', :num_staff=>2, :num_managers=>3}
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
|
|
3
|
+
describe "Sequel core extensions" do
|
|
4
|
+
specify "should not be used inside Sequel, to insure Sequel works without them" do
|
|
5
|
+
usage = []
|
|
6
|
+
match_re = /(\.(all_two_pairs\?|sql_value_list|sql_array|sql_expr|sql_negate|sql_or|sql_string_join|lit|to_sequel_blob|case|sql_expr_if_all_two_pairs)\W)|:\w+\.(qualify|identifier|as|cast|asc|desc|sql_subscript|\*|sql_function)\W/
|
|
7
|
+
comment_re = /^\s*#|# core_sql/
|
|
8
|
+
Dir['lib/sequel/**/*.rb'].each do |f|
|
|
9
|
+
lines = File.read(f).split("\n").grep(match_re).delete_if{|l| l =~ comment_re}
|
|
10
|
+
usage << [f, lines] unless lines.empty?
|
|
11
|
+
end
|
|
12
|
+
puts usage unless usage.empty?
|
|
13
|
+
usage.should be_empty
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
specify "should have Sequel.core_extensions? be true if enabled" do
|
|
17
|
+
Sequel.core_extensions?.should be_true
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
3
21
|
describe "Array#all_two_pairs?" do
|
|
4
22
|
specify "should return false if empty" do
|
|
5
23
|
[].all_two_pairs?.should == false
|
|
@@ -285,41 +303,11 @@ describe "Symbol" do
|
|
|
285
303
|
@oe.class.should == Sequel::SQL::OrderedExpression
|
|
286
304
|
@oe.descending.should == false
|
|
287
305
|
end
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
describe "Dataset#literal" do
|
|
291
|
-
before do
|
|
292
|
-
@ds = Sequel::Database.new.dataset
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
specify "should convert qualified symbol notation into dot notation" do
|
|
296
|
-
@ds.literal(:abc__def).should == 'abc.def'
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
specify "should convert AS symbol notation into SQL AS notation" do
|
|
300
|
-
@ds.literal(:xyz___x).should == 'xyz AS x'
|
|
301
|
-
@ds.literal(:abc__def___x).should == 'abc.def AS x'
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
specify "should support names with digits" do
|
|
305
|
-
@ds.literal(:abc2).should == 'abc2'
|
|
306
|
-
@ds.literal(:xx__yy3).should == 'xx.yy3'
|
|
307
|
-
@ds.literal(:ab34__temp3_4ax).should == 'ab34.temp3_4ax'
|
|
308
|
-
@ds.literal(:x1___y2).should == 'x1 AS y2'
|
|
309
|
-
@ds.literal(:abc2__def3___ggg4).should == 'abc2.def3 AS ggg4'
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
specify "should support upper case and lower case" do
|
|
313
|
-
@ds.literal(:ABC).should == 'ABC'
|
|
314
|
-
@ds.literal(:Zvashtoy__aBcD).should == 'Zvashtoy.aBcD'
|
|
315
|
-
end
|
|
316
306
|
|
|
317
|
-
specify "should
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
@ds.literal(:
|
|
321
|
-
@ds.literal(:"aB cD___XX XX").should == '"aB cD" AS "XX XX"'
|
|
322
|
-
@ds.literal(:"Zva shtoy__aB cD___XX XX").should == '"Zva shtoy"."aB cD" AS "XX XX"'
|
|
307
|
+
specify "should work correctly with objects" do
|
|
308
|
+
o = Object.new
|
|
309
|
+
def o.sql_literal(ds) "(foo)" end
|
|
310
|
+
@ds.literal(:column.qualify(o)).should == '(foo)."COLUMN"'
|
|
323
311
|
end
|
|
324
312
|
end
|
|
325
313
|
|
|
@@ -341,6 +329,7 @@ describe "Symbol" do
|
|
|
341
329
|
@ds.literal(:abc.sql_subscript(1)).should == "abc[1]"
|
|
342
330
|
@ds.literal(:abc__def.sql_subscript(1)).should == "abc.def[1]"
|
|
343
331
|
@ds.literal(:abc.sql_subscript(1)|2).should == "abc[1, 2]"
|
|
332
|
+
@ds.literal(:abc.sql_subscript(1)[2]).should == "abc[1][2]"
|
|
344
333
|
end
|
|
345
334
|
|
|
346
335
|
specify "should support cast_numeric and cast_string" do
|
|
@@ -380,63 +369,3 @@ describe "Symbol" do
|
|
|
380
369
|
:abc.extract(:year).to_s(@ds).should == "extract(year FROM abc)"
|
|
381
370
|
end
|
|
382
371
|
end
|
|
383
|
-
|
|
384
|
-
describe "Sequel::SQL::Function#==" do
|
|
385
|
-
specify "should be true for functions with the same name and arguments, false otherwise" do
|
|
386
|
-
a = :date.sql_function(:t)
|
|
387
|
-
b = :date.sql_function(:t)
|
|
388
|
-
a.should == b
|
|
389
|
-
(a == b).should == true
|
|
390
|
-
c = :date.sql_function(:c)
|
|
391
|
-
a.should_not == c
|
|
392
|
-
(a == c).should == false
|
|
393
|
-
d = :time.sql_function(:c)
|
|
394
|
-
a.should_not == d
|
|
395
|
-
c.should_not == d
|
|
396
|
-
(a == d).should == false
|
|
397
|
-
(c == d).should == false
|
|
398
|
-
end
|
|
399
|
-
end
|
|
400
|
-
|
|
401
|
-
describe "Sequel::SQL::OrderedExpression" do
|
|
402
|
-
specify "should #desc" do
|
|
403
|
-
@oe = :column.asc
|
|
404
|
-
@oe.descending.should == false
|
|
405
|
-
@oe.desc.descending.should == true
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
specify "should #asc" do
|
|
409
|
-
@oe = :column.desc
|
|
410
|
-
@oe.descending.should == true
|
|
411
|
-
@oe.asc.descending.should == false
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
specify "should #invert" do
|
|
415
|
-
@oe = :column.desc
|
|
416
|
-
@oe.invert.descending.should == false
|
|
417
|
-
@oe.invert.invert.descending.should == true
|
|
418
|
-
end
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
describe "Expression" do
|
|
422
|
-
specify "should consider objects == only if they have the same attributes" do
|
|
423
|
-
:column.qualify(:table).cast(:type).*(:numeric_column).asc.should == :column.qualify(:table).cast(:type).*(:numeric_column).asc
|
|
424
|
-
:other_column.qualify(:table).cast(:type).*(:numeric_column).asc.should_not == :column.qualify(:table).cast(:type).*(:numeric_column).asc
|
|
425
|
-
|
|
426
|
-
:column.qualify(:table).cast(:type).*(:numeric_column).asc.should eql(:column.qualify(:table).cast(:type).*(:numeric_column).asc)
|
|
427
|
-
:other_column.qualify(:table).cast(:type).*(:numeric_column).asc.should_not eql(:column.qualify(:table).cast(:type).*(:numeric_column).asc)
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
specify "should use the same hash value for objects that have the same attributes" do
|
|
431
|
-
:column.qualify(:table).cast(:type).*(:numeric_column).asc.hash.should == :column.qualify(:table).cast(:type).*(:numeric_column).asc.hash
|
|
432
|
-
:other_column.qualify(:table).cast(:type).*(:numeric_column).asc.hash.should_not == :column.qualify(:table).cast(:type).*(:numeric_column).asc.hash
|
|
433
|
-
|
|
434
|
-
h = {}
|
|
435
|
-
a = :column.qualify(:table).cast(:type).*(:numeric_column).asc
|
|
436
|
-
b = :column.qualify(:table).cast(:type).*(:numeric_column).asc
|
|
437
|
-
h[a] = 1
|
|
438
|
-
h[b] = 2
|
|
439
|
-
h[a].should == 2
|
|
440
|
-
h[b].should == 2
|
|
441
|
-
end
|
|
442
|
-
end
|
|
@@ -74,12 +74,13 @@ describe "force_encoding plugin" do
|
|
|
74
74
|
|
|
75
75
|
specify "should work when saving new model instances" do
|
|
76
76
|
o = @c.new
|
|
77
|
-
|
|
77
|
+
ds = MODEL_DB[:a]
|
|
78
78
|
def ds.first
|
|
79
79
|
s = 'blah'
|
|
80
80
|
s.force_encoding('US-ASCII')
|
|
81
81
|
{:id=>1, :x=>s}
|
|
82
82
|
end
|
|
83
|
+
@c.dataset = ds
|
|
83
84
|
o.save
|
|
84
85
|
o.x.should == 'blah'
|
|
85
86
|
o.x.encoding.should == @e1
|
|
@@ -87,12 +88,13 @@ describe "force_encoding plugin" do
|
|
|
87
88
|
|
|
88
89
|
specify "should work when refreshing model instances" do
|
|
89
90
|
o = @c.load(:id=>1, :x=>'as')
|
|
90
|
-
|
|
91
|
+
ds = MODEL_DB[:a]
|
|
91
92
|
def ds.first
|
|
92
93
|
s = 'blah'
|
|
93
94
|
s.force_encoding('US-ASCII')
|
|
94
95
|
{:id=>1, :x=>s}
|
|
95
96
|
end
|
|
97
|
+
@c.dataset = ds
|
|
96
98
|
o.refresh
|
|
97
99
|
o.x.should == 'blah'
|
|
98
100
|
o.x.encoding.should == @e1
|
|
@@ -308,7 +308,7 @@ describe "Model#before_destroy && Model#after_destroy" do
|
|
|
308
308
|
@c.before_destroy {MODEL_DB << "BLAH before"}
|
|
309
309
|
m = @c.load(:id => 2233)
|
|
310
310
|
m.destroy
|
|
311
|
-
MODEL_DB.sqls.should == ['BLAH before', "DELETE FROM items WHERE
|
|
311
|
+
MODEL_DB.sqls.should == ['BLAH before', "DELETE FROM items WHERE id = 2233", 'BLAH after']
|
|
312
312
|
end
|
|
313
313
|
|
|
314
314
|
specify "#destroy should cancel the destroy and raise an error if before_destroy returns false and raise_on_save_failure is true" do
|
|
@@ -402,7 +402,7 @@ end
|
|
|
402
402
|
|
|
403
403
|
describe "Model#add_hook_type" do
|
|
404
404
|
before do
|
|
405
|
-
class Foo < Sequel::Model(:items)
|
|
405
|
+
class ::Foo < Sequel::Model(:items)
|
|
406
406
|
add_hook_type :before_bar, :after_bar
|
|
407
407
|
|
|
408
408
|
def bar
|
|
@@ -413,6 +413,9 @@ describe "Model#add_hook_type" do
|
|
|
413
413
|
end
|
|
414
414
|
@f = Class.new(Foo)
|
|
415
415
|
end
|
|
416
|
+
after do
|
|
417
|
+
Object.send(:remove_const, :Foo)
|
|
418
|
+
end
|
|
416
419
|
|
|
417
420
|
specify "should have before_bar and after_bar class methods" do
|
|
418
421
|
@f.should respond_to(:before_bar)
|
|
@@ -218,6 +218,23 @@ describe "Sequel::Plugins::IdentityMap" do
|
|
|
218
218
|
end
|
|
219
219
|
end
|
|
220
220
|
|
|
221
|
+
it "should not use the identity map as a lookup cache if a dynamic callback is used" do
|
|
222
|
+
@c1.many_to_one :artist, :class=>@c2
|
|
223
|
+
@c.with_identity_map do
|
|
224
|
+
MODEL_DB.sqls.length.should == 0
|
|
225
|
+
o = @c1.load(:id=>1, :artist_id=>2)
|
|
226
|
+
a = o.artist
|
|
227
|
+
a.should be_a_kind_of(@c2)
|
|
228
|
+
MODEL_DB.sqls.length.should == 1
|
|
229
|
+
o = @c1.load(:id=>2, :artist_id=>2)
|
|
230
|
+
o.artist.should == a
|
|
231
|
+
MODEL_DB.sqls.length.should == 0
|
|
232
|
+
o = @c1.load(:id=>3, :artist_id=>3)
|
|
233
|
+
o.artist.should_not == a
|
|
234
|
+
MODEL_DB.sqls.length.should == 1
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
221
238
|
it "should not override custom :eager_loaders for many_to_many associations" do
|
|
222
239
|
@c1.columns :id
|
|
223
240
|
@c2.columns :id
|
|
@@ -21,7 +21,7 @@ describe "instance_filters plugin" do
|
|
|
21
21
|
|
|
22
22
|
specify "should raise an error when destroying a stale record" do
|
|
23
23
|
@p.destroy
|
|
24
|
-
MODEL_DB.sqls.should == ["DELETE FROM people WHERE
|
|
24
|
+
MODEL_DB.sqls.should == ["DELETE FROM people WHERE id = 1"]
|
|
25
25
|
@p.instance_filter(:name=>'Jim')
|
|
26
26
|
@p.this.numrows = 0
|
|
27
27
|
proc{@p.destroy}.should raise_error(Sequel::Plugins::InstanceFilters::Error)
|
|
@@ -11,7 +11,7 @@ describe "Sequel::Plugins::LazyAttributes" do
|
|
|
11
11
|
meta_def(:columns){[:id, :name]}
|
|
12
12
|
lazy_attributes :name
|
|
13
13
|
meta_def(:columns){[:id]}
|
|
14
|
-
dataset._fetch = proc do |sql|
|
|
14
|
+
instance_dataset._fetch = dataset._fetch = proc do |sql|
|
|
15
15
|
if sql !~ /WHERE/
|
|
16
16
|
if sql =~ /name/
|
|
17
17
|
[{:id=>1, :name=>'1'}, {:id=>2, :name=>'2'}]
|
|
@@ -133,7 +133,7 @@ describe "Sequel::Plugins::LazyAttributes" do
|
|
|
133
133
|
|
|
134
134
|
it "should work with the serialization plugin" do
|
|
135
135
|
@c.plugin :serialization, :yaml, :name
|
|
136
|
-
@ds._fetch = [[{:id=>1}, {:id=>2}], [{:id=>1, :name=>"--- 3\n"}, {:id=>2, :name=>"--- 6\n"}], [{:id=>1}], [{:name=>"--- 3\n"}]]
|
|
136
|
+
@c.instance_dataset._fetch = @ds._fetch = [[{:id=>1}, {:id=>2}], [{:id=>1, :name=>"--- 3\n"}, {:id=>2, :name=>"--- 6\n"}], [{:id=>1}], [{:name=>"--- 3\n"}]]
|
|
137
137
|
@c.with_identity_map do
|
|
138
138
|
ms = @ds.all
|
|
139
139
|
ms.map{|m| m.values}.should == [{:id=>1}, {:id=>2}]
|
|
@@ -76,8 +76,8 @@ describe "List plugin" do
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
it "should have position field set to max+1 when creating if not already set" do
|
|
79
|
-
@c.dataset._fetch = [[{:pos=>nil}], [{:id=>1, :position=>1}], [{:pos=>1}], [{:id=>2, :position=>2}]]
|
|
80
|
-
@c.dataset.autoid = 1
|
|
79
|
+
@c.instance_dataset._fetch = @c.dataset._fetch = [[{:pos=>nil}], [{:id=>1, :position=>1}], [{:pos=>1}], [{:id=>2, :position=>2}]]
|
|
80
|
+
@c.instance_dataset.autoid = @c.dataset.autoid = 1
|
|
81
81
|
@c.create.values.should == {:id=>1, :position=>1}
|
|
82
82
|
@c.create.values.should == {:id=>2, :position=>2}
|
|
83
83
|
@db.sqls.should == ["SELECT max(position) FROM items LIMIT 1",
|
|
@@ -89,8 +89,8 @@ describe "List plugin" do
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
it "should have position field set to max+1 in scope when creating if not already set" do
|
|
92
|
-
@sc.dataset._fetch = [[{:pos=>nil}], [{:id=>1, :scope_id=>1, :position=>1}], [{:pos=>1}], [{:id=>2, :scope_id=>1, :position=>2}], [{:pos=>nil}], [{:id=>3, :scope_id=>2, :position=>1}]]
|
|
93
|
-
@sc.dataset.autoid = 1
|
|
92
|
+
@sc.instance_dataset._fetch = @sc.dataset._fetch = [[{:pos=>nil}], [{:id=>1, :scope_id=>1, :position=>1}], [{:pos=>1}], [{:id=>2, :scope_id=>1, :position=>2}], [{:pos=>nil}], [{:id=>3, :scope_id=>2, :position=>1}]]
|
|
93
|
+
@sc.instance_dataset.autoid = @sc.dataset.autoid = 1
|
|
94
94
|
@sc.create(:scope_id=>1).values.should == {:id=>1, :scope_id=>1, :position=>1}
|
|
95
95
|
@sc.create(:scope_id=>1).values.should == {:id=>2, :scope_id=>1, :position=>2}
|
|
96
96
|
@sc.create(:scope_id=>2).values.should == {:id=>3, :scope_id=>2, :position=>1}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::ManyToOnePkLookup" do
|
|
4
|
+
before do
|
|
5
|
+
class ::LookupModel < ::Sequel::Model
|
|
6
|
+
plugin :many_to_one_pk_lookup
|
|
7
|
+
columns :id, :caching_model_id, :caching_model_id2
|
|
8
|
+
many_to_one :caching_model
|
|
9
|
+
many_to_one :caching_model2, :key=>[:caching_model_id, :caching_model_id2], :class=>:CachingModel
|
|
10
|
+
end
|
|
11
|
+
@c = LookupModel
|
|
12
|
+
|
|
13
|
+
class ::CachingModel < Sequel::Model
|
|
14
|
+
columns :id, :id2
|
|
15
|
+
end
|
|
16
|
+
@cc = CachingModel
|
|
17
|
+
|
|
18
|
+
@db = MODEL_DB
|
|
19
|
+
end
|
|
20
|
+
after do
|
|
21
|
+
Object.send(:remove_const, :CachingModel)
|
|
22
|
+
Object.send(:remove_const, :LookupModel)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
shared_examples_for "many_to_one_pk_lookup with composite keys" do
|
|
26
|
+
it "should use a simple primary key lookup when retrieving many_to_one associated records" do
|
|
27
|
+
@db.sqls.should == []
|
|
28
|
+
@c.load(:id=>3, :caching_model_id=>1, :caching_model_id2=>2).caching_model2.should equal(@cm12)
|
|
29
|
+
@c.load(:id=>3, :caching_model_id=>2, :caching_model_id2=>1).caching_model2.should equal(@cm21)
|
|
30
|
+
@db.sqls.should == []
|
|
31
|
+
@c.load(:id=>4, :caching_model_id=>2, :caching_model_id2=>2).caching_model2
|
|
32
|
+
@db.sqls.should_not == []
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
shared_examples_for "many_to_one_pk_lookup" do
|
|
37
|
+
it "should use a simple primary key lookup when retrieving many_to_one associated records via a composite key" do
|
|
38
|
+
@cc.set_primary_key([:id, :id2])
|
|
39
|
+
@db.sqls.should == []
|
|
40
|
+
@c.load(:id=>3, :caching_model_id=>1).caching_model.should equal(@cm1)
|
|
41
|
+
@c.load(:id=>4, :caching_model_id=>2).caching_model.should equal(@cm2)
|
|
42
|
+
@db.sqls.should == []
|
|
43
|
+
@c.load(:id=>4, :caching_model_id=>3).caching_model
|
|
44
|
+
@db.sqls.should_not == []
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should not use a simple primary key lookup if the assocation has a nil :key option" do
|
|
48
|
+
@c.many_to_one :caching_model, :key=>nil, :dataset=>proc{CachingModel.filter(:caching_model_id=>caching_model_id)}
|
|
49
|
+
@c.load(:id=>3, :caching_model_id=>1).caching_model
|
|
50
|
+
@db.sqls.should_not == []
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should not use a simple primary key lookup if the assocation has a nil :key option" do
|
|
54
|
+
@c.many_to_one :caching_model, :many_to_one_pk_lookup=>false
|
|
55
|
+
@c.load(:id=>3, :caching_model_id=>1).caching_model
|
|
56
|
+
@db.sqls.should_not == []
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should not use a simple primary key lookup if the assocation's :primary_key option doesn't match the primary key of the associated class" do
|
|
60
|
+
@c.many_to_one :caching_model, :primary_key=>:id2
|
|
61
|
+
@c.load(:id=>3, :caching_model_id=>1).caching_model
|
|
62
|
+
@db.sqls.should_not == []
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should not use a simple primary key lookup if the prepared_statements_associations method is being used" do
|
|
66
|
+
c2 = Class.new(Sequel::Model(:not_caching_model))
|
|
67
|
+
c2.dataset._fetch = {:id=>1}
|
|
68
|
+
c = Class.new(Sequel::Model(:lookup_model))
|
|
69
|
+
c.class_eval do
|
|
70
|
+
plugin :prepared_statements_associations
|
|
71
|
+
plugin :many_to_one_pk_lookup
|
|
72
|
+
columns :id, :caching_model_id
|
|
73
|
+
many_to_one :caching_model, :class=>c2
|
|
74
|
+
end
|
|
75
|
+
c.load(:id=>3, :caching_model_id=>1).caching_model.should == c2.load(:id=>1)
|
|
76
|
+
@db.sqls.should_not == []
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should use a simple primary key lookup if the prepared_statements_associations method is being used but associated model also uses caching" do
|
|
80
|
+
c = Class.new(Sequel::Model(:lookup_model))
|
|
81
|
+
c.class_eval do
|
|
82
|
+
plugin :prepared_statements_associations
|
|
83
|
+
plugin :many_to_one_pk_lookup
|
|
84
|
+
columns :id, :caching_model_id
|
|
85
|
+
many_to_one :caching_model
|
|
86
|
+
end
|
|
87
|
+
c.load(:id=>3, :caching_model_id=>1).caching_model.should equal(@cm1)
|
|
88
|
+
@db.sqls.should == []
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe "With caching plugin" do
|
|
93
|
+
before do
|
|
94
|
+
@cache_class = Class.new(Hash) do
|
|
95
|
+
attr_accessor :ttl
|
|
96
|
+
def set(k, v, ttl); self[k] = v; @ttl = ttl; end
|
|
97
|
+
def get(k); self[k]; end
|
|
98
|
+
end
|
|
99
|
+
cache = @cache_class.new
|
|
100
|
+
@cache = cache
|
|
101
|
+
|
|
102
|
+
@cc.plugin :caching, @cache
|
|
103
|
+
@cc.dataset._fetch = {:id=>1}
|
|
104
|
+
@cm1 = @cc[1]
|
|
105
|
+
@cm2 = @cc[2]
|
|
106
|
+
@cm12 = @cc[1, 2]
|
|
107
|
+
@cm21 = @cc[2, 1]
|
|
108
|
+
|
|
109
|
+
@db.reset
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it_should_behave_like "many_to_one_pk_lookup"
|
|
113
|
+
it_should_behave_like "many_to_one_pk_lookup with composite keys"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe "With static_cache plugin with single key" do
|
|
117
|
+
before do
|
|
118
|
+
@cc.dataset._fetch = [{:id=>1}, {:id=>2}]
|
|
119
|
+
@cc.plugin :static_cache
|
|
120
|
+
@cm1 = @cc[1]
|
|
121
|
+
@cm2 = @cc[2]
|
|
122
|
+
@db.reset
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it_should_behave_like "many_to_one_pk_lookup"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
describe "With static_cache plugin with composite key" do
|
|
129
|
+
before do
|
|
130
|
+
@cc.set_primary_key([:id, :id2])
|
|
131
|
+
@cc.dataset._fetch = [{:id=>1, :id2=>2}, {:id=>2, :id2=>1}]
|
|
132
|
+
@cc.plugin :static_cache
|
|
133
|
+
@cm12 = @cc[[1, 2]]
|
|
134
|
+
@cm21 = @cc[[2, 1]]
|
|
135
|
+
@db.reset
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it_should_behave_like "many_to_one_pk_lookup with composite keys"
|
|
139
|
+
end
|
|
140
|
+
end
|