sequel 3.46.0 → 3.47.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.
- 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
|