sequel 3.46.0 → 3.47.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +96 -0
- data/Rakefile +7 -1
- data/bin/sequel +6 -4
- data/doc/active_record.rdoc +1 -1
- data/doc/advanced_associations.rdoc +14 -35
- data/doc/association_basics.rdoc +66 -4
- data/doc/migration.rdoc +4 -0
- data/doc/opening_databases.rdoc +6 -0
- data/doc/postgresql.rdoc +302 -0
- data/doc/release_notes/3.47.0.txt +270 -0
- data/doc/security.rdoc +6 -0
- data/lib/sequel/adapters/ibmdb.rb +9 -9
- data/lib/sequel/adapters/jdbc.rb +22 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +7 -2
- data/lib/sequel/adapters/mock.rb +2 -0
- data/lib/sequel/adapters/postgres.rb +44 -13
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/adapters/shared/mysql.rb +2 -2
- data/lib/sequel/adapters/shared/postgres.rb +94 -55
- data/lib/sequel/adapters/shared/sqlite.rb +3 -1
- data/lib/sequel/adapters/sqlite.rb +2 -2
- data/lib/sequel/adapters/utils/pg_types.rb +1 -14
- data/lib/sequel/adapters/utils/split_alter_table.rb +3 -3
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +2 -2
- data/lib/sequel/database/features.rb +5 -0
- data/lib/sequel/database/misc.rb +47 -5
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/dataset/actions.rb +4 -2
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/query.rb +8 -6
- data/lib/sequel/dataset/sql.rb +8 -6
- data/lib/sequel/extensions/constraint_validations.rb +5 -2
- data/lib/sequel/extensions/migration.rb +10 -8
- data/lib/sequel/extensions/pagination.rb +3 -0
- data/lib/sequel/extensions/pg_array.rb +85 -25
- data/lib/sequel/extensions/pg_hstore.rb +8 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +4 -1
- data/lib/sequel/extensions/pg_inet.rb +16 -13
- data/lib/sequel/extensions/pg_interval.rb +6 -2
- data/lib/sequel/extensions/pg_json.rb +18 -11
- data/lib/sequel/extensions/pg_range.rb +17 -2
- data/lib/sequel/extensions/pg_range_ops.rb +7 -5
- data/lib/sequel/extensions/pg_row.rb +29 -12
- data/lib/sequel/extensions/pretty_table.rb +3 -0
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/schema_caching.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +3 -1
- data/lib/sequel/extensions/select_remove.rb +3 -0
- data/lib/sequel/model.rb +8 -2
- data/lib/sequel/model/associations.rb +39 -27
- data/lib/sequel/model/base.rb +99 -38
- data/lib/sequel/model/plugins.rb +25 -0
- data/lib/sequel/plugins/association_autoreloading.rb +27 -22
- data/lib/sequel/plugins/association_dependencies.rb +1 -7
- data/lib/sequel/plugins/auto_validations.rb +110 -0
- data/lib/sequel/plugins/boolean_readers.rb +1 -6
- data/lib/sequel/plugins/caching.rb +6 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
- data/lib/sequel/plugins/composition.rb +14 -7
- data/lib/sequel/plugins/constraint_validations.rb +2 -13
- data/lib/sequel/plugins/defaults_setter.rb +1 -6
- data/lib/sequel/plugins/dirty.rb +8 -0
- data/lib/sequel/plugins/error_splitter.rb +54 -0
- data/lib/sequel/plugins/force_encoding.rb +1 -5
- data/lib/sequel/plugins/hook_class_methods.rb +1 -6
- data/lib/sequel/plugins/input_transformer.rb +79 -0
- data/lib/sequel/plugins/instance_filters.rb +7 -1
- data/lib/sequel/plugins/instance_hooks.rb +7 -1
- data/lib/sequel/plugins/json_serializer.rb +5 -10
- data/lib/sequel/plugins/lazy_attributes.rb +20 -7
- data/lib/sequel/plugins/list.rb +1 -6
- data/lib/sequel/plugins/many_through_many.rb +1 -2
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +23 -39
- data/lib/sequel/plugins/optimistic_locking.rb +1 -5
- data/lib/sequel/plugins/pg_row.rb +4 -2
- data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -7
- data/lib/sequel/plugins/prepared_statements.rb +1 -5
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -11
- data/lib/sequel/plugins/rcte_tree.rb +2 -2
- data/lib/sequel/plugins/serialization.rb +11 -13
- data/lib/sequel/plugins/serialization_modification_detection.rb +13 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/static_cache.rb +67 -19
- data/lib/sequel/plugins/string_stripper.rb +7 -27
- data/lib/sequel/plugins/subclasses.rb +3 -5
- data/lib/sequel/plugins/tactical_eager_loading.rb +2 -2
- data/lib/sequel/plugins/timestamps.rb +2 -7
- data/lib/sequel/plugins/touch.rb +5 -8
- data/lib/sequel/plugins/tree.rb +1 -6
- data/lib/sequel/plugins/typecast_on_load.rb +1 -5
- data/lib/sequel/plugins/update_primary_key.rb +26 -14
- data/lib/sequel/plugins/validation_class_methods.rb +31 -16
- data/lib/sequel/plugins/validation_helpers.rb +50 -26
- data/lib/sequel/plugins/xml_serializer.rb +3 -6
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +131 -15
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/core/connection_pool_spec.rb +16 -17
- data/spec/core/database_spec.rb +111 -40
- data/spec/core/dataset_spec.rb +65 -74
- data/spec/core/expression_filters_spec.rb +6 -5
- data/spec/core/object_graph_spec.rb +0 -1
- data/spec/core/schema_spec.rb +23 -23
- data/spec/core/spec_helper.rb +5 -1
- data/spec/extensions/association_dependencies_spec.rb +1 -1
- data/spec/extensions/association_proxies_spec.rb +1 -1
- data/spec/extensions/auto_validations_spec.rb +90 -0
- data/spec/extensions/caching_spec.rb +6 -0
- data/spec/extensions/class_table_inheritance_spec.rb +8 -1
- data/spec/extensions/composition_spec.rb +12 -5
- data/spec/extensions/constraint_validations_spec.rb +4 -4
- data/spec/extensions/core_refinements_spec.rb +29 -79
- data/spec/extensions/dirty_spec.rb +14 -0
- data/spec/extensions/error_splitter_spec.rb +18 -0
- data/spec/extensions/identity_map_spec.rb +0 -1
- data/spec/extensions/input_transformer_spec.rb +54 -0
- data/spec/extensions/instance_filters_spec.rb +6 -0
- data/spec/extensions/instance_hooks_spec.rb +12 -1
- data/spec/extensions/json_serializer_spec.rb +0 -1
- data/spec/extensions/lazy_attributes_spec.rb +64 -55
- data/spec/extensions/looser_typecasting_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +3 -4
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +53 -15
- data/spec/extensions/migration_spec.rb +16 -0
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/pg_array_spec.rb +48 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +10 -2
- data/spec/extensions/pg_hstore_spec.rb +5 -0
- data/spec/extensions/pg_inet_spec.rb +5 -0
- data/spec/extensions/pg_interval_spec.rb +7 -3
- data/spec/extensions/pg_json_spec.rb +6 -1
- data/spec/extensions/pg_range_ops_spec.rb +4 -1
- data/spec/extensions/pg_range_spec.rb +5 -0
- data/spec/extensions/pg_row_plugin_spec.rb +13 -0
- data/spec/extensions/pg_row_spec.rb +28 -19
- data/spec/extensions/pg_typecast_on_load_spec.rb +6 -1
- data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +1 -1
- data/spec/extensions/rcte_tree_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/serialization_modification_detection_spec.rb +8 -0
- data/spec/extensions/serialization_spec.rb +15 -1
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/static_cache_spec.rb +59 -9
- data/spec/extensions/tactical_eager_loading_spec.rb +19 -4
- data/spec/extensions/update_primary_key_spec.rb +17 -1
- data/spec/extensions/validation_class_methods_spec.rb +25 -0
- data/spec/extensions/validation_helpers_spec.rb +59 -3
- data/spec/integration/associations_test.rb +5 -5
- data/spec/integration/eager_loader_test.rb +32 -63
- data/spec/integration/model_test.rb +2 -2
- data/spec/integration/plugin_test.rb +88 -56
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +1 -1
- data/spec/integration/timezone_test.rb +0 -1
- data/spec/integration/transaction_test.rb +0 -1
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +106 -84
- data/spec/model/base_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +8 -8
- data/spec/model/model_spec.rb +27 -9
- data/spec/model/plugins_spec.rb +71 -0
- data/spec/model/record_spec.rb +99 -13
- metadata +12 -2
@@ -18,12 +18,17 @@ describe Sequel::Model, "PgTypecastOnLoad plugin" do
|
|
18
18
|
@c.first.refresh.values.should == {:id=>1, :b=>true, :y=>0}
|
19
19
|
end
|
20
20
|
|
21
|
+
specify "should not fail if schema oid does not have a related conversion proc" do
|
22
|
+
@c.db_schema[:b][:oid] = 0
|
23
|
+
@c.first.refresh.values.should == {:id=>1, :b=>"t", :y=>0}
|
24
|
+
end
|
25
|
+
|
21
26
|
specify "should call the database conversion proc with value when automatically reloading the object on creation via insert_select" do
|
22
27
|
@c.dataset.meta_def(:insert_select){|h| insert(h); first}
|
23
28
|
@c.create.values.should == {:id=>1, :b=>true, :y=>0}
|
24
29
|
end
|
25
30
|
|
26
|
-
specify "should allowing setting columns separately via
|
31
|
+
specify "should allowing setting columns separately via add_pg_typecast_on_load_columns" do
|
27
32
|
@c = Class.new(Sequel::Model(@db[:items]))
|
28
33
|
@c.plugin :pg_typecast_on_load
|
29
34
|
@c.first.values.should == {:id=>1, :b=>"t", :y=>"0"}
|
@@ -34,7 +34,7 @@ describe "query_literals extension" do
|
|
34
34
|
@ds.select_more('a, b, c').sql.should == 'SELECT d, a, b, c FROM t'
|
35
35
|
end
|
36
36
|
|
37
|
-
it "should have #
|
37
|
+
it "should have #select_more use placeholder literal string if given a string and additional arguments" do
|
38
38
|
@ds.select_more('a, b, ?', 1).sql.should == 'SELECT d, a, b, 1 FROM t'
|
39
39
|
end
|
40
40
|
|
@@ -144,7 +144,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
144
144
|
[{:id=>2, :name=>'AA', :parent_id=>1, :x_root_x=>2},
|
145
145
|
{:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>1}, {:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>2},
|
146
146
|
{:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>2}, {:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>1}]]
|
147
|
-
|
147
|
+
@ds.eager(:ancestors).all
|
148
148
|
sqls = MODEL_DB.sqls
|
149
149
|
sqls.first.should == "SELECT * FROM nodes"
|
150
150
|
sqls.last.should =~ /WITH t AS \(SELECT id AS x_root_x, nodes\.\* FROM nodes WHERE \(\(id IN \([12], [12]\)\) AND \(i = 1\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.parent_id = nodes\.id\) WHERE \(i = 1\)\) SELECT \* FROM t AS nodes WHERE \(i = 1\)/
|
@@ -236,7 +236,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
236
236
|
[{:id=>6, :parent_id=>2, :name=>'C', :x_root_x=>2}, {:id=>9, :parent_id=>2, :name=>'E', :x_root_x=>2},
|
237
237
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2},
|
238
238
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7}]]
|
239
|
-
|
239
|
+
@ds.eager(:descendants).all
|
240
240
|
sqls = MODEL_DB.sqls
|
241
241
|
sqls.first.should == "SELECT * FROM nodes"
|
242
242
|
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\* FROM nodes WHERE \(\(parent_id IN \([267], [267], [267]\)\) AND \(i = 1\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\) WHERE \(i = 1\)\) SELECT \* FROM t AS nodes WHERE \(i = 1\)/
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
2
|
|
3
|
-
describe Sequel::Model, "
|
3
|
+
describe Sequel::Model, "set_schema" do
|
4
4
|
before do
|
5
5
|
@model = Class.new(Sequel::Model(:items))
|
6
6
|
@model.plugin :schema
|
@@ -8,7 +8,7 @@ describe Sequel::Model, "dataset & schema" do
|
|
8
8
|
|
9
9
|
specify "sets schema with implicit table name" do
|
10
10
|
@model.set_schema do
|
11
|
-
primary_key :ssn, :string
|
11
|
+
primary_key :ssn, :type=>:string
|
12
12
|
end
|
13
13
|
@model.primary_key.should == :ssn
|
14
14
|
@model.table_name.should == :items
|
@@ -69,4 +69,12 @@ describe "serialization_modification_detection plugin" do
|
|
69
69
|
@o4.save
|
70
70
|
@o4.changed_columns.should == []
|
71
71
|
end
|
72
|
+
|
73
|
+
it "should work with frozen objects" do
|
74
|
+
@o1.changed_columns.should == []
|
75
|
+
@o1.h.should == {}
|
76
|
+
@o1.freeze
|
77
|
+
@o1.h[1] = 2
|
78
|
+
@o1.changed_columns.should == [:h]
|
79
|
+
end
|
72
80
|
end
|
@@ -76,7 +76,6 @@ describe "Serialization plugin" do
|
|
76
76
|
it "should translate values to and from yaml serialization format using accessor methods" do
|
77
77
|
@c.set_primary_key :id
|
78
78
|
@c.plugin :serialization, :yaml, :abc, :def
|
79
|
-
vals = nil
|
80
79
|
@c.dataset._fetch = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
|
81
80
|
|
82
81
|
o = @c.first
|
@@ -290,4 +289,19 @@ describe "Serialization plugin" do
|
|
290
289
|
o = @c.load(:abc => 3)
|
291
290
|
o.abc.should == 9
|
292
291
|
end
|
292
|
+
|
293
|
+
it "should work correctly with frozen instances" do
|
294
|
+
@c.set_primary_key :id
|
295
|
+
@c.plugin :serialization, :yaml, :abc, :def
|
296
|
+
@c.dataset._fetch = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
|
297
|
+
|
298
|
+
o = @c.first
|
299
|
+
o.freeze
|
300
|
+
o.abc.should == 1
|
301
|
+
o.abc.should == 1
|
302
|
+
o.def.should == "hello"
|
303
|
+
o.def.should == "hello"
|
304
|
+
proc{o.abc = 2}.should raise_error
|
305
|
+
proc{o.def = 'h'}.should raise_error
|
306
|
+
end
|
293
307
|
end
|
@@ -161,7 +161,7 @@ describe "sharding plugin" do
|
|
161
161
|
end
|
162
162
|
|
163
163
|
specify "should not override a server already set on an associated object" do
|
164
|
-
|
164
|
+
@Album.server(:s1).first
|
165
165
|
artist = @Artist.server(:s2).first
|
166
166
|
@db.sqls.should == ["SELECT * FROM albums LIMIT 1 -- s1", "SELECT * FROM artists LIMIT 1 -- s2"]
|
167
167
|
|
@@ -67,13 +67,27 @@ describe "Sequel::Plugins::StaticCache" do
|
|
67
67
|
@db.sqls.should == []
|
68
68
|
end
|
69
69
|
|
70
|
-
it "should have
|
70
|
+
it "should have count with no argument or block not issue a query" do
|
71
|
+
@c.count.should == 2
|
72
|
+
@db.sqls.should == []
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should have count with argument or block not issue a query" do
|
76
|
+
@db.fetch = [[{:count=>1}], [{:count=>2}]]
|
77
|
+
@c.count(:a).should == 1
|
78
|
+
@c.count{b}.should == 2
|
79
|
+
@db.sqls.should == ["SELECT COUNT(a) AS count FROM t LIMIT 1", "SELECT COUNT(b) AS count FROM t LIMIT 1"]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should have map not send a query if given an argument" do
|
71
83
|
@c.map(:id).sort.should == [1, 2]
|
72
|
-
@db.sqls.should == [
|
84
|
+
@db.sqls.should == []
|
85
|
+
@c.map([:id,:id]).sort.should == [[1,1], [2,2]]
|
86
|
+
@db.sqls.should == []
|
73
87
|
end
|
74
88
|
|
75
89
|
it "should have map without a block or argument not raise an exception or issue a query" do
|
76
|
-
@c.map
|
90
|
+
@c.map.to_a.should == @c.all
|
77
91
|
@db.sqls.should == []
|
78
92
|
end
|
79
93
|
|
@@ -81,6 +95,10 @@ describe "Sequel::Plugins::StaticCache" do
|
|
81
95
|
@c.map.frozen?.should be_false
|
82
96
|
end
|
83
97
|
|
98
|
+
it "should have map with a block and argument raise" do
|
99
|
+
proc{@c.map(:id){}}.should raise_error(Sequel::Error)
|
100
|
+
end
|
101
|
+
|
84
102
|
it "should have other enumerable methods work without sending a query" do
|
85
103
|
a = @c.sort_by{|o| o.id}
|
86
104
|
a.first.should equal(@c1)
|
@@ -88,7 +106,7 @@ describe "Sequel::Plugins::StaticCache" do
|
|
88
106
|
@db.sqls.should == []
|
89
107
|
end
|
90
108
|
|
91
|
-
it "should have all just return the
|
109
|
+
it "should have all just return the cached values" do
|
92
110
|
a = @c.all.sort_by{|o| o.id}
|
93
111
|
a.first.should equal(@c1)
|
94
112
|
a.last.should equal(@c2)
|
@@ -105,22 +123,54 @@ describe "Sequel::Plugins::StaticCache" do
|
|
105
123
|
|
106
124
|
it "should have to_hash without arguments return the cached objects without a query" do
|
107
125
|
a = @c.to_hash
|
126
|
+
a.should == {1=>@c1, 2=>@c2}
|
108
127
|
a[1].should equal(@c1)
|
109
128
|
a[2].should equal(@c2)
|
110
129
|
@db.sqls.should == []
|
111
130
|
end
|
112
131
|
|
113
|
-
it "should have to_hash with
|
114
|
-
@c.to_hash(:id)
|
115
|
-
|
132
|
+
it "should have to_hash with arguments return the cached objects without a query" do
|
133
|
+
a = @c.to_hash(:id)
|
134
|
+
a.should == {1=>@c1, 2=>@c2}
|
135
|
+
a[1].should equal(@c1)
|
136
|
+
a[2].should equal(@c2)
|
137
|
+
|
138
|
+
a = @c.to_hash([:id])
|
139
|
+
a.should == {[1]=>@c1, [2]=>@c2}
|
140
|
+
a[[1]].should equal(@c1)
|
141
|
+
a[[2]].should equal(@c2)
|
142
|
+
|
116
143
|
@c.to_hash(:id, :id).should == {1=>1, 2=>2}
|
117
|
-
@
|
144
|
+
@c.to_hash([:id], :id).should == {[1]=>1, [2]=>2}
|
145
|
+
@c.to_hash(:id, [:id]).should == {1=>[1], 2=>[2]}
|
146
|
+
@c.to_hash([:id], [:id]).should == {[1]=>[1], [2]=>[2]}
|
147
|
+
|
148
|
+
@db.sqls.should == []
|
118
149
|
end
|
119
150
|
|
120
|
-
it "should have
|
151
|
+
it "should have to_hash not return a frozen object" do
|
121
152
|
@c.to_hash.frozen?.should be_false
|
122
153
|
end
|
123
154
|
|
155
|
+
it "should have to_hash_groups without arguments return the cached objects without a query" do
|
156
|
+
a = @c.to_hash_groups(:id)
|
157
|
+
a.should == {1=>[@c1], 2=>[@c2]}
|
158
|
+
a[1].first.should equal(@c1)
|
159
|
+
a[2].first.should equal(@c2)
|
160
|
+
|
161
|
+
a = @c.to_hash_groups([:id])
|
162
|
+
a.should == {[1]=>[@c1], [2]=>[@c2]}
|
163
|
+
a[[1]].first.should equal(@c1)
|
164
|
+
a[[2]].first.should equal(@c2)
|
165
|
+
|
166
|
+
@c.to_hash_groups(:id, :id).should == {1=>[1], 2=>[2]}
|
167
|
+
@c.to_hash_groups([:id], :id).should == {[1]=>[1], [2]=>[2]}
|
168
|
+
@c.to_hash_groups(:id, [:id]).should == {1=>[[1]], 2=>[[2]]}
|
169
|
+
@c.to_hash_groups([:id], [:id]).should == {[1]=>[[1]], [2]=>[[2]]}
|
170
|
+
|
171
|
+
@db.sqls.should == []
|
172
|
+
end
|
173
|
+
|
124
174
|
it "all of the static cache values (model instances) should be frozen" do
|
125
175
|
@c.all.all?{|o| o.frozen?}.should be_true
|
126
176
|
end
|
@@ -2,7 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
3
3
|
describe "Sequel::Plugins::TacticalEagerLoading" do
|
4
4
|
before do
|
5
|
-
class ::
|
5
|
+
class ::TacticalEagerLoadingModel < Sequel::Model
|
6
6
|
plugin :tactical_eager_loading
|
7
7
|
columns :id, :parent_id
|
8
8
|
many_to_one :parent, :class=>self
|
@@ -10,6 +10,8 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
10
10
|
dataset._fetch = proc do |sql|
|
11
11
|
if sql !~ /WHERE/
|
12
12
|
[{:id=>1, :parent_id=>101}, {:id=>2, :parent_id=>102}, {:id=>101, :parent_id=>nil}, {:id=>102, :parent_id=>nil}]
|
13
|
+
elsif sql =~ /WHERE.*\bid = (\d+)/
|
14
|
+
[{:id=>$1.to_i, :parent_id=>nil}]
|
13
15
|
elsif sql =~ /WHERE.*\bid IN \(([\d, ]*)\)/
|
14
16
|
$1.split(', ').map{|x| {:id=>x.to_i, :parent_id=>nil}}
|
15
17
|
elsif sql =~ /WHERE.*\bparent_id IN \(([\d, ]*)\)/
|
@@ -17,12 +19,12 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
20
|
-
@c = ::
|
21
|
-
@ds =
|
22
|
+
@c = ::TacticalEagerLoadingModel
|
23
|
+
@ds = TacticalEagerLoadingModel.dataset
|
22
24
|
MODEL_DB.reset
|
23
25
|
end
|
24
26
|
after do
|
25
|
-
Object.send(:remove_const, :
|
27
|
+
Object.send(:remove_const, :TacticalEagerLoadingModel)
|
26
28
|
end
|
27
29
|
|
28
30
|
it "Dataset#all should set the retrieved_by and retrieved_with attributes" do
|
@@ -60,4 +62,17 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
60
62
|
@c.all{|x| x.parent2 if x.is_a?(c)}
|
61
63
|
end
|
62
64
|
|
65
|
+
it "association getter methods should not eagerly load the association if an instance is frozen" do
|
66
|
+
ts = @c.all
|
67
|
+
ts.first.freeze
|
68
|
+
MODEL_DB.sqls.length.should == 1
|
69
|
+
ts.map{|x| x.parent}.should == [ts[2], ts[3], nil, nil]
|
70
|
+
MODEL_DB.sqls.length.should == 2
|
71
|
+
ts.map{|x| x.children}.should == [[], [], [ts[0]], [ts[1]]]
|
72
|
+
MODEL_DB.sqls.length.should == 2
|
73
|
+
ts.map{|x| x.parent}.should == [ts[2], ts[3], nil, nil]
|
74
|
+
MODEL_DB.sqls.length.should == 1
|
75
|
+
ts.map{|x| x.children}.should == [[], [], [ts[0]], [ts[1]]]
|
76
|
+
MODEL_DB.sqls.length.should == 1
|
77
|
+
end
|
63
78
|
end
|
@@ -7,7 +7,6 @@ describe "Sequel::Plugins::UpdatePrimaryKey" do
|
|
7
7
|
@c.columns :a, :b
|
8
8
|
@c.set_primary_key :a
|
9
9
|
@c.unrestrict_primary_key
|
10
|
-
@o = @c.new
|
11
10
|
@ds = @c.dataset
|
12
11
|
MODEL_DB.reset
|
13
12
|
end
|
@@ -68,4 +67,21 @@ describe "Sequel::Plugins::UpdatePrimaryKey" do
|
|
68
67
|
@c.all.should == [@c.load(:a=>2, :b=>5)]
|
69
68
|
MODEL_DB.sqls.should == ["SELECT * FROM a LIMIT 1", "UPDATE a SET a = 2 WHERE (a = 1)", "UPDATE a SET b = 4 WHERE (a = 2)", "UPDATE a SET b = 5 WHERE (a = 2)", "SELECT * FROM a"]
|
70
69
|
end
|
70
|
+
|
71
|
+
specify "should clear the associations cache of non-many_to_one associations when changing the primary key" do
|
72
|
+
@c.one_to_many :cs, :class=>@c
|
73
|
+
@c.many_to_one :c, :class=>@c
|
74
|
+
o = @c.new(:a=>1)
|
75
|
+
o.associations[:cs] = @c.new
|
76
|
+
o.associations[:c] = o2 = @c.new
|
77
|
+
o.a = 2
|
78
|
+
o.associations.should == {:c=>o2}
|
79
|
+
end
|
80
|
+
|
81
|
+
specify "should handle frozen instances" do
|
82
|
+
o = @c.new
|
83
|
+
o.a = 1
|
84
|
+
o.freeze
|
85
|
+
o.pk_hash.should == {:a=>1}
|
86
|
+
end
|
71
87
|
end
|
@@ -799,6 +799,31 @@ describe Sequel::Model, "Validations" do
|
|
799
799
|
@person.should be_valid
|
800
800
|
end
|
801
801
|
|
802
|
+
it "should validate that a column has the correct type for the schema column" do
|
803
|
+
p = model_class.call Sequel::Model do
|
804
|
+
columns :age, :d
|
805
|
+
self.raise_on_typecast_failure = false
|
806
|
+
validates_schema_type :age
|
807
|
+
validates_schema_type :d, :message=>'is a bad choice'
|
808
|
+
@db_schema = {:age=>{:type=>:integer}, :d=>{:type=>:date}}
|
809
|
+
end
|
810
|
+
|
811
|
+
@person = p.new
|
812
|
+
@person.should be_valid
|
813
|
+
|
814
|
+
@person.age = 'a'
|
815
|
+
@person.should_not be_valid
|
816
|
+
@person.errors.full_messages.should == ['age is not a valid integer']
|
817
|
+
@person.age = 1
|
818
|
+
@person.should be_valid
|
819
|
+
|
820
|
+
@person.d = 'a'
|
821
|
+
@person.should_not be_valid
|
822
|
+
@person.errors.full_messages.should == ['d is a bad choice']
|
823
|
+
@person.d = Date.today
|
824
|
+
@person.should be_valid
|
825
|
+
end
|
826
|
+
|
802
827
|
it "should validate numericality of column" do
|
803
828
|
class ::Person < Sequel::Model
|
804
829
|
validations.clear
|
@@ -247,6 +247,22 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
247
247
|
@m.errors.full_messages.should == ['value is not a valid integer']
|
248
248
|
end
|
249
249
|
|
250
|
+
specify "should support validates_schema_types" do
|
251
|
+
@c.set_validations{validates_schema_types}
|
252
|
+
@m.value = 123
|
253
|
+
@m.should be_valid
|
254
|
+
@m.value = '123'
|
255
|
+
@m.should be_valid
|
256
|
+
@m.meta_def(:db_schema){{:value=>{:type=>:integer}}}
|
257
|
+
@m.should_not be_valid
|
258
|
+
@m.errors.full_messages.should == ['value is not a valid integer']
|
259
|
+
|
260
|
+
@c.set_validations{validates_schema_types(:value)}
|
261
|
+
@m.meta_def(:db_schema){{:value=>{:type=>:integer}}}
|
262
|
+
@m.should_not be_valid
|
263
|
+
@m.errors.full_messages.should == ['value is not a valid integer']
|
264
|
+
end
|
265
|
+
|
250
266
|
specify "should support validates_numeric" do
|
251
267
|
@c.set_validations{validates_numeric(:value)}
|
252
268
|
@m.value = 'blah'
|
@@ -279,29 +295,57 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
279
295
|
@m.should be_valid
|
280
296
|
@m.value = '123'
|
281
297
|
@m.should_not be_valid
|
282
|
-
@m.errors.full_messages.should == ['value is not a
|
298
|
+
@m.errors.full_messages.should == ['value is not a valid integer']
|
283
299
|
|
284
300
|
@c.set_validations{validates_type(:String, :value)}
|
285
301
|
@m.value = '123'
|
286
302
|
@m.should be_valid
|
287
303
|
@m.value = 123
|
288
304
|
@m.should_not be_valid
|
289
|
-
@m.errors.full_messages.should == ['value is not a
|
305
|
+
@m.errors.full_messages.should == ['value is not a valid string']
|
290
306
|
|
291
307
|
@c.set_validations{validates_type('Integer', :value)}
|
292
308
|
@m.value = 123
|
293
309
|
@m.should be_valid
|
294
310
|
@m.value = 123.05
|
295
311
|
@m.should_not be_valid
|
296
|
-
@m.errors.full_messages.should == ['value is not a
|
312
|
+
@m.errors.full_messages.should == ['value is not a valid integer']
|
297
313
|
|
298
314
|
@c.set_validations{validates_type(Integer, :value)}
|
299
315
|
@m.value = nil
|
300
316
|
@m.should be_valid
|
301
317
|
@m.value = false
|
302
318
|
@m.should_not be_valid
|
319
|
+
|
320
|
+
@c.set_validations{validates_type([Integer, Float], :value)}
|
321
|
+
@m.value = nil
|
322
|
+
@m.should be_valid
|
323
|
+
@m.value = 1
|
324
|
+
@m.should be_valid
|
325
|
+
@m.value = 1.0
|
326
|
+
@m.should be_valid
|
327
|
+
@m.value = BigDecimal.new('1.0')
|
328
|
+
@m.should_not be_valid
|
329
|
+
@m.errors.full_messages.should == ['value is not a valid integer or float']
|
303
330
|
end
|
304
331
|
|
332
|
+
specify "should support validates_not_null" do
|
333
|
+
@c.set_validations{validates_not_null(:value)}
|
334
|
+
@m.should_not be_valid
|
335
|
+
@m.value = ''
|
336
|
+
@m.should be_valid
|
337
|
+
@m.value = 1234
|
338
|
+
@m.should be_valid
|
339
|
+
@m.value = nil
|
340
|
+
@m.should_not be_valid
|
341
|
+
@m.value = true
|
342
|
+
@m.should be_valid
|
343
|
+
@m.value = false
|
344
|
+
@m.should be_valid
|
345
|
+
@m.value = Time.now
|
346
|
+
@m.should be_valid
|
347
|
+
end
|
348
|
+
|
305
349
|
specify "should support validates_presence" do
|
306
350
|
@c.set_validations{validates_presence(:value)}
|
307
351
|
@m.should_not be_valid
|
@@ -466,4 +510,16 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
466
510
|
m.should be_valid
|
467
511
|
MODEL_DB.sqls.should == ["SELECT COUNT(*) AS count FROM items WHERE ((username = '2') AND (password = '1') AND (id != 3)) LIMIT 1"]
|
468
512
|
end
|
513
|
+
|
514
|
+
it "should not attempt a database query if the underlying columns have validation errors" do
|
515
|
+
@c.columns(:id, :username, :password)
|
516
|
+
@c.set_dataset MODEL_DB[:items]
|
517
|
+
@c.set_validations{validates_not_string(:username); validates_unique([:username, :password])}
|
518
|
+
@c.dataset._fetch = {:v=>0}
|
519
|
+
|
520
|
+
MODEL_DB.reset
|
521
|
+
m = @c.new(:username => "1", :password => "anothertest")
|
522
|
+
m.should_not be_valid
|
523
|
+
MODEL_DB.sqls.should == []
|
524
|
+
end
|
469
525
|
end
|