sequel 3.21.0 → 3.29.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 +413 -3
- data/README.rdoc +20 -6
- data/Rakefile +23 -16
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +86 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +115 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +15 -7
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +5 -31
- data/lib/sequel/adapters/jdbc/db2.rb +44 -0
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +26 -17
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +107 -38
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +78 -182
- data/lib/sequel/adapters/mysql2.rb +24 -23
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +349 -51
- data/lib/sequel/adapters/postgres.rb +169 -21
- data/lib/sequel/adapters/shared/access.rb +21 -6
- data/lib/sequel/adapters/shared/db2.rb +288 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +108 -65
- data/lib/sequel/adapters/shared/mysql.rb +56 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -34
- data/lib/sequel/adapters/shared/postgres.rb +107 -58
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +168 -41
- data/lib/sequel/adapters/sqlite.rb +27 -18
- data/lib/sequel/adapters/swift/mysql.rb +9 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +152 -17
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +100 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +194 -57
- data/lib/sequel/dataset/features.rb +81 -8
- data/lib/sequel/dataset/graph.rb +8 -7
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +32 -15
- data/lib/sequel/dataset/query.rb +223 -42
- data/lib/sequel/dataset/sql.rb +58 -61
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +997 -331
- data/lib/sequel/model/base.rb +386 -129
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -25
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +44 -35
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +65 -29
- data/spec/adapters/mysql_spec.rb +122 -123
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +213 -61
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +729 -508
- data/spec/core/dataset_spec.rb +980 -1044
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +4 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +522 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +375 -62
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +200 -120
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +174 -7
- data/spec/model/associations_spec.rb +849 -661
- data/spec/model/base_spec.rb +255 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +640 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +207 -167
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +321 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +95 -38
data/spec/model/base_spec.rb
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
3
|
describe "Model attribute setters" do
|
|
4
|
-
|
|
5
|
-
before(:each) do
|
|
6
|
-
MODEL_DB.reset
|
|
7
|
-
|
|
4
|
+
before do
|
|
8
5
|
@c = Class.new(Sequel::Model(:items)) do
|
|
9
6
|
columns :id, :x, :y, :"x y"
|
|
10
7
|
end
|
|
11
8
|
@o = @c.new
|
|
9
|
+
MODEL_DB.reset
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
it "should mark the column value as changed" do
|
|
@@ -41,18 +39,13 @@ describe Sequel::Model, "dataset" do
|
|
|
41
39
|
before do
|
|
42
40
|
@a = Class.new(Sequel::Model(:items))
|
|
43
41
|
@b = Class.new(Sequel::Model)
|
|
44
|
-
|
|
45
|
-
class
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
class ShoeSize < Sequel::Model
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
class BootSize < ShoeSize
|
|
55
|
-
end
|
|
42
|
+
class ::Elephant < Sequel::Model(:ele1); end
|
|
43
|
+
class ::Maggot < Sequel::Model; end
|
|
44
|
+
class ::ShoeSize < Sequel::Model; end
|
|
45
|
+
class ::BootSize < ShoeSize; end
|
|
46
|
+
end
|
|
47
|
+
after do
|
|
48
|
+
[:Elephant, :Maggot, :ShoeSize, :BootSize].each{|x| Object.send(:remove_const, x)}
|
|
56
49
|
end
|
|
57
50
|
|
|
58
51
|
specify "should default to the plural of the class name" do
|
|
@@ -74,33 +67,59 @@ describe Sequel::Model, "dataset" do
|
|
|
74
67
|
end
|
|
75
68
|
|
|
76
69
|
specify "should disregard namespaces for the table name" do
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
begin
|
|
71
|
+
module ::BlahBlah
|
|
72
|
+
class MwaHaHa < Sequel::Model
|
|
73
|
+
end
|
|
79
74
|
end
|
|
80
|
-
end
|
|
81
75
|
|
|
82
|
-
|
|
76
|
+
BlahBlah::MwaHaHa.dataset.sql.should == 'SELECT * FROM mwa_ha_has'
|
|
77
|
+
ensure
|
|
78
|
+
Object.send(:remove_const, :BlahBlah)
|
|
79
|
+
end
|
|
83
80
|
end
|
|
84
81
|
end
|
|
85
82
|
|
|
86
83
|
describe Sequel::Model, ".def_dataset_method" do
|
|
87
84
|
before do
|
|
88
|
-
@c = Class.new(Sequel::Model(:items))
|
|
89
|
-
end
|
|
85
|
+
@c = Class.new(Sequel::Model(:items))
|
|
90
86
|
end
|
|
91
87
|
|
|
92
88
|
it "should add a method to the dataset and model if called with a block argument" do
|
|
93
|
-
@c.
|
|
94
|
-
def_dataset_method(:return_3){3}
|
|
95
|
-
end
|
|
89
|
+
@c.def_dataset_method(:return_3){3}
|
|
96
90
|
@c.return_3.should == 3
|
|
97
91
|
@c.dataset.return_3.should == 3
|
|
98
92
|
end
|
|
99
93
|
|
|
100
|
-
it "should
|
|
94
|
+
it "should handle weird method names" do
|
|
95
|
+
@c.def_dataset_method(:"return 3"){3}
|
|
96
|
+
@c.send(:"return 3").should == 3
|
|
97
|
+
@c.dataset.send(:"return 3").should == 3
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "should not add a model method if the model already responds to the method" do
|
|
101
101
|
@c.instance_eval do
|
|
102
|
-
|
|
102
|
+
def foo
|
|
103
|
+
1
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def bar
|
|
109
|
+
2
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def_dataset_method(:foo){3}
|
|
113
|
+
def_dataset_method(:bar){4}
|
|
103
114
|
end
|
|
115
|
+
@c.foo.should == 1
|
|
116
|
+
@c.dataset.foo.should == 3
|
|
117
|
+
@c.send(:bar).should == 2
|
|
118
|
+
@c.dataset.bar.should == 4
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "should add all passed methods to the model if called without a block argument" do
|
|
122
|
+
@c.def_dataset_method(:return_3, :return_4)
|
|
104
123
|
proc{@c.return_3}.should raise_error(NoMethodError)
|
|
105
124
|
proc{@c.return_4}.should raise_error(NoMethodError)
|
|
106
125
|
@c.dataset.instance_eval do
|
|
@@ -112,30 +131,113 @@ describe Sequel::Model, ".def_dataset_method" do
|
|
|
112
131
|
end
|
|
113
132
|
|
|
114
133
|
it "should cache calls and readd methods if set_dataset is used" do
|
|
115
|
-
@c.
|
|
116
|
-
def_dataset_method(:return_3){3}
|
|
117
|
-
end
|
|
134
|
+
@c.def_dataset_method(:return_3){3}
|
|
118
135
|
@c.set_dataset :items
|
|
119
136
|
@c.return_3.should == 3
|
|
120
137
|
@c.dataset.return_3.should == 3
|
|
121
138
|
end
|
|
122
139
|
|
|
123
140
|
it "should readd methods to subclasses, if set_dataset is used in a subclass" do
|
|
124
|
-
@c.
|
|
125
|
-
|
|
126
|
-
|
|
141
|
+
@c.def_dataset_method(:return_3){3}
|
|
142
|
+
c = Class.new(@c)
|
|
143
|
+
c.set_dataset :items
|
|
144
|
+
c.return_3.should == 3
|
|
145
|
+
c.dataset.return_3.should == 3
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
describe Sequel::Model, ".dataset_module" do
|
|
150
|
+
before do
|
|
151
|
+
@c = Class.new(Sequel::Model(:items))
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "should extend the dataset with the module if the model has a dataset" do
|
|
155
|
+
@c.dataset_module{def return_3() 3 end}
|
|
156
|
+
@c.dataset.return_3.should == 3
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "should add methods defined in the module to the class" do
|
|
160
|
+
@c.dataset_module{def return_3() 3 end}
|
|
161
|
+
@c.return_3.should == 3
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it "should cache calls and readd methods if set_dataset is used" do
|
|
165
|
+
@c.dataset_module{def return_3() 3 end}
|
|
166
|
+
@c.set_dataset :items
|
|
167
|
+
@c.return_3.should == 3
|
|
168
|
+
@c.dataset.return_3.should == 3
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "should readd methods to subclasses, if set_dataset is used in a subclass" do
|
|
172
|
+
@c.dataset_module{def return_3() 3 end}
|
|
127
173
|
c = Class.new(@c)
|
|
128
174
|
c.set_dataset :items
|
|
129
175
|
c.return_3.should == 3
|
|
130
176
|
c.dataset.return_3.should == 3
|
|
131
177
|
end
|
|
178
|
+
|
|
179
|
+
it "should only have a single dataset_module per class" do
|
|
180
|
+
@c.dataset_module{def return_3() 3 end}
|
|
181
|
+
@c.dataset_module{def return_3() 3 + (begin; super; rescue NoMethodError; 1; end) end}
|
|
182
|
+
@c.return_3.should == 4
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it "should not have subclasses share the dataset_module" do
|
|
186
|
+
@c.dataset_module{def return_3() 3 end}
|
|
187
|
+
c = Class.new(@c)
|
|
188
|
+
c.dataset_module{def return_3() 3 + (begin; super; rescue NoMethodError; 1; end) end}
|
|
189
|
+
c.return_3.should == 6
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "should accept a module object and extend the dataset with it" do
|
|
193
|
+
@c.dataset_module Module.new{def return_3() 3 end}
|
|
194
|
+
@c.dataset.return_3.should == 3
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "should be able to call dataset_module with a module multiple times" do
|
|
198
|
+
@c.dataset_module Module.new{def return_3() 3 end}
|
|
199
|
+
@c.dataset_module Module.new{def return_4() 4 end}
|
|
200
|
+
@c.dataset.return_3.should == 3
|
|
201
|
+
@c.dataset.return_4.should == 4
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "should be able mix dataset_module calls with and without arguments" do
|
|
205
|
+
@c.dataset_module{def return_3() 3 end}
|
|
206
|
+
@c.dataset_module Module.new{def return_4() 4 end}
|
|
207
|
+
@c.dataset.return_3.should == 3
|
|
208
|
+
@c.dataset.return_4.should == 4
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it "should have modules provided to dataset_module extend subclass datasets" do
|
|
212
|
+
@c.dataset_module{def return_3() 3 end}
|
|
213
|
+
@c.dataset_module Module.new{def return_4() 4 end}
|
|
214
|
+
c = Class.new(@c)
|
|
215
|
+
c.set_dataset :a
|
|
216
|
+
c.dataset.return_3.should == 3
|
|
217
|
+
c.dataset.return_4.should == 4
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it "should return the dataset module if given a block" do
|
|
221
|
+
Object.new.extend(@c.dataset_module{def return_3() 3 end}).return_3.should == 3
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it "should return the argument if given one" do
|
|
225
|
+
Object.new.extend(@c.dataset_module Module.new{def return_3() 3 end}).return_3.should == 3
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it "should raise error if called with both an argument and ablock" do
|
|
229
|
+
proc{@c.dataset_module(Module.new{def return_3() 3 end}){}}.should raise_error(Sequel::Error)
|
|
230
|
+
end
|
|
132
231
|
end
|
|
133
232
|
|
|
134
233
|
describe "A model class with implicit table name" do
|
|
135
234
|
before do
|
|
136
|
-
class Donkey < Sequel::Model
|
|
235
|
+
class ::Donkey < Sequel::Model
|
|
137
236
|
end
|
|
138
237
|
end
|
|
238
|
+
after do
|
|
239
|
+
Object.send(:remove_const, :Donkey)
|
|
240
|
+
end
|
|
139
241
|
|
|
140
242
|
specify "should have a dataset associated with the model class" do
|
|
141
243
|
Donkey.dataset.model.should == Donkey
|
|
@@ -144,11 +246,12 @@ end
|
|
|
144
246
|
|
|
145
247
|
describe "A model inheriting from a model" do
|
|
146
248
|
before do
|
|
147
|
-
class Feline < Sequel::Model
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
249
|
+
class ::Feline < Sequel::Model; end
|
|
250
|
+
class ::Leopard < Feline; end
|
|
251
|
+
end
|
|
252
|
+
after do
|
|
253
|
+
Object.send(:remove_const, :Leopard)
|
|
254
|
+
Object.send(:remove_const, :Feline)
|
|
152
255
|
end
|
|
153
256
|
|
|
154
257
|
specify "should have a dataset associated with itself" do
|
|
@@ -228,29 +331,27 @@ end
|
|
|
228
331
|
|
|
229
332
|
describe "Model.db=" do
|
|
230
333
|
before do
|
|
231
|
-
|
|
232
|
-
|
|
334
|
+
@db1 = Sequel.mock
|
|
335
|
+
@db2 = Sequel.mock
|
|
233
336
|
|
|
234
|
-
|
|
235
|
-
set_dataset $db1[:blue].filter(:x=>1)
|
|
236
|
-
end
|
|
337
|
+
@m = Class.new(Sequel::Model(@db1[:blue].filter(:x=>1)))
|
|
237
338
|
end
|
|
238
339
|
|
|
239
340
|
specify "should affect the underlying dataset" do
|
|
240
|
-
|
|
341
|
+
@m.db = @db2
|
|
241
342
|
|
|
242
|
-
|
|
243
|
-
|
|
343
|
+
@m.dataset.db.should === @db2
|
|
344
|
+
@m.dataset.db.should_not === @db1
|
|
244
345
|
end
|
|
245
346
|
|
|
246
347
|
specify "should keep the same dataset options" do
|
|
247
|
-
|
|
248
|
-
|
|
348
|
+
@m.db = @db2
|
|
349
|
+
@m.dataset.sql.should == 'SELECT * FROM blue WHERE (x = 1)'
|
|
249
350
|
end
|
|
250
351
|
|
|
251
352
|
specify "should use the database for subclasses" do
|
|
252
|
-
|
|
253
|
-
Class.new(
|
|
353
|
+
@m.db = @db2
|
|
354
|
+
Class.new(@m).db.should === @db2
|
|
254
355
|
end
|
|
255
356
|
end
|
|
256
357
|
|
|
@@ -258,9 +359,6 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
|
|
|
258
359
|
before do
|
|
259
360
|
@c = Class.new(Sequel::Model(:blahblah)) do
|
|
260
361
|
columns :x, :y, :z
|
|
261
|
-
def _refresh(ds)
|
|
262
|
-
self
|
|
263
|
-
end
|
|
264
362
|
end
|
|
265
363
|
@c.strict_param_setting = false
|
|
266
364
|
@c.instance_variable_set(:@columns, [:x, :y, :z])
|
|
@@ -288,9 +386,12 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
|
|
|
288
386
|
i.values.should == {:x => 1, :y => 2}
|
|
289
387
|
i.set(:x => 4, :y => 5, :z => 6)
|
|
290
388
|
i.values.should == {:x => 4, :y => 5}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
i
|
|
389
|
+
|
|
390
|
+
@c.dataset._fetch = {:x => 7}
|
|
391
|
+
i = @c.new
|
|
392
|
+
i.update(:x => 7, :z => 9)
|
|
393
|
+
i.values.should == {:x => 7}
|
|
394
|
+
MODEL_DB.sqls.should == ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
|
|
294
395
|
end
|
|
295
396
|
|
|
296
397
|
it "should not set restricted columns by default" do
|
|
@@ -299,9 +400,12 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
|
|
|
299
400
|
i.values.should == {:x => 1, :y => 2}
|
|
300
401
|
i.set(:x => 4, :y => 5, :z => 6)
|
|
301
402
|
i.values.should == {:x => 4, :y => 5}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
i
|
|
403
|
+
|
|
404
|
+
@c.dataset._fetch = {:x => 7}
|
|
405
|
+
i = @c.new
|
|
406
|
+
i.update(:x => 7, :z => 9)
|
|
407
|
+
i.values.should == {:x => 7}
|
|
408
|
+
MODEL_DB.sqls.should == ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
|
|
305
409
|
end
|
|
306
410
|
|
|
307
411
|
it "should have allowed take precedence over restricted" do
|
|
@@ -311,9 +415,12 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
|
|
|
311
415
|
i.values.should == {:x => 1, :y => 2}
|
|
312
416
|
i.set(:x => 4, :y => 5, :z => 6)
|
|
313
417
|
i.values.should == {:x => 4, :y => 5}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
i
|
|
418
|
+
|
|
419
|
+
@c.dataset._fetch = {:y => 7}
|
|
420
|
+
i = @c.new
|
|
421
|
+
i.update(:y => 7, :z => 9)
|
|
422
|
+
i.values.should == {:y => 7}
|
|
423
|
+
MODEL_DB.sqls.should == ["INSERT INTO blahblah (y) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
|
|
317
424
|
end
|
|
318
425
|
end
|
|
319
426
|
|
|
@@ -322,12 +429,8 @@ describe Sequel::Model, ".(un)?restrict_primary_key\\??" do
|
|
|
322
429
|
@c = Class.new(Sequel::Model(:blahblah)) do
|
|
323
430
|
set_primary_key :id
|
|
324
431
|
columns :x, :y, :z, :id
|
|
325
|
-
def refresh
|
|
326
|
-
self
|
|
327
|
-
end
|
|
328
432
|
end
|
|
329
433
|
@c.strict_param_setting = false
|
|
330
|
-
@c.instance_variable_set(:@columns, [:x, :y, :z])
|
|
331
434
|
end
|
|
332
435
|
|
|
333
436
|
it "should restrict updates to primary key by default" do
|
|
@@ -364,11 +467,7 @@ describe Sequel::Model, ".strict_param_setting" do
|
|
|
364
467
|
@c = Class.new(Sequel::Model(:blahblah)) do
|
|
365
468
|
columns :x, :y, :z, :id
|
|
366
469
|
set_restricted_columns :z
|
|
367
|
-
def refresh
|
|
368
|
-
self
|
|
369
|
-
end
|
|
370
470
|
end
|
|
371
|
-
@c.instance_variable_set(:@columns, [:x, :y, :z])
|
|
372
471
|
end
|
|
373
472
|
|
|
374
473
|
it "should be enabled by default" do
|
|
@@ -425,20 +524,18 @@ end
|
|
|
425
524
|
|
|
426
525
|
describe Sequel::Model, ".[] optimization" do
|
|
427
526
|
before do
|
|
428
|
-
@
|
|
429
|
-
@
|
|
430
|
-
|
|
431
|
-
@simple_table
|
|
432
|
-
end
|
|
433
|
-
end
|
|
527
|
+
@db = MODEL_DB.clone
|
|
528
|
+
@db.quote_identifiers = true
|
|
529
|
+
@c = Class.new(Sequel::Model(@db))
|
|
434
530
|
end
|
|
435
531
|
|
|
436
532
|
it "should set simple_pk to the literalized primary key column name if a single primary key" do
|
|
437
|
-
@c.
|
|
533
|
+
@c.set_primary_key :id
|
|
534
|
+
@c.simple_pk.should == '"id"'
|
|
438
535
|
@c.set_primary_key :b
|
|
439
|
-
@c.simple_pk.should == 'b'
|
|
536
|
+
@c.simple_pk.should == '"b"'
|
|
440
537
|
@c.set_primary_key :b__a.identifier
|
|
441
|
-
@c.simple_pk.should == 'b__a'
|
|
538
|
+
@c.simple_pk.should == '"b__a"'
|
|
442
539
|
end
|
|
443
540
|
|
|
444
541
|
it "should have simple_pk be blank if compound or no primary key" do
|
|
@@ -452,36 +549,99 @@ describe Sequel::Model, ".[] optimization" do
|
|
|
452
549
|
|
|
453
550
|
it "should have simple table set if passed a Symbol to set_dataset" do
|
|
454
551
|
@c.set_dataset :a
|
|
455
|
-
@c.simple_table.should == 'a'
|
|
552
|
+
@c.simple_table.should == '"a"'
|
|
456
553
|
@c.set_dataset :b
|
|
457
|
-
@c.simple_table.should == 'b'
|
|
554
|
+
@c.simple_table.should == '"b"'
|
|
458
555
|
@c.set_dataset :b__a
|
|
459
|
-
@c.simple_table.should == 'b.a'
|
|
556
|
+
@c.simple_table.should == '"b"."a"'
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
it "should have simple_table set if passed a simple select all dataset to set_dataset" do
|
|
560
|
+
@c.set_dataset @db[:a]
|
|
561
|
+
@c.simple_table.should == '"a"'
|
|
562
|
+
@c.set_dataset @db[:b]
|
|
563
|
+
@c.simple_table.should == '"b"'
|
|
564
|
+
@c.set_dataset @db[:b__a]
|
|
565
|
+
@c.simple_table.should == '"b"."a"'
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
it "should simple_pk and simple_table respect dataset's identifier input methods" do
|
|
569
|
+
ds = @db[:ab]
|
|
570
|
+
ds.identifier_input_method = :reverse
|
|
571
|
+
@c.set_dataset ds
|
|
572
|
+
@c.simple_table.should == '"ba"'
|
|
573
|
+
@c.set_primary_key :cd
|
|
574
|
+
@c.simple_pk.should == '"dc"'
|
|
575
|
+
|
|
576
|
+
@c.set_dataset ds.from(:ef__gh)
|
|
577
|
+
@c.simple_table.should == '"fe"."hg"'
|
|
460
578
|
end
|
|
461
579
|
|
|
462
|
-
it "should have simple_table = nil if passed a dataset to set_dataset" do
|
|
463
|
-
@c.set_dataset @c.db[:a]
|
|
580
|
+
it "should have simple_table = nil if passed a non-simple select all dataset to set_dataset" do
|
|
581
|
+
@c.set_dataset @c.db[:a].filter(:active)
|
|
464
582
|
@c.simple_table.should == nil
|
|
465
583
|
end
|
|
466
584
|
|
|
467
585
|
it "should have simple_table superclasses setting if inheriting" do
|
|
468
|
-
@c.set_dataset :a
|
|
469
|
-
Class.new(@c).simple_table.should == 'a'
|
|
470
|
-
@c.instance_variable_set(:@simple_table, nil)
|
|
471
586
|
Class.new(@c).simple_table.should == nil
|
|
472
|
-
@c.
|
|
473
|
-
Class.new(@c).simple_table.should == "'
|
|
587
|
+
@c.set_dataset :a
|
|
588
|
+
Class.new(@c).simple_table.should == '"a"'
|
|
474
589
|
end
|
|
475
590
|
|
|
476
591
|
it "should use Dataset#with_sql if simple_table and simple_pk are true" do
|
|
477
592
|
@c.set_dataset :a
|
|
478
|
-
@c.dataset.
|
|
479
|
-
@c[1]
|
|
593
|
+
@c.dataset._fetch = {:id => 1}
|
|
594
|
+
@c[1].should == @c.load(:id=>1)
|
|
595
|
+
@db.sqls.should == ['SELECT * FROM "a" WHERE "id" = 1']
|
|
480
596
|
end
|
|
481
597
|
|
|
482
598
|
it "should not use Dataset#with_sql if either simple_table or simple_pk is nil" do
|
|
483
|
-
@c.set_dataset @
|
|
484
|
-
@c.dataset.
|
|
485
|
-
@c[1]
|
|
599
|
+
@c.set_dataset @db[:a].filter(:active)
|
|
600
|
+
@c.dataset._fetch = {:id => 1}
|
|
601
|
+
@c[1].should == @c.load(:id=>1)
|
|
602
|
+
@db.sqls.should == ['SELECT * FROM "a" WHERE ("active" AND ("id" = 1)) LIMIT 1']
|
|
603
|
+
end
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
describe "Model datasets #with_pk" do
|
|
607
|
+
before do
|
|
608
|
+
@c = Class.new(Sequel::Model(:a))
|
|
609
|
+
@ds = @c.dataset
|
|
610
|
+
@ds._fetch = {:id=>1}
|
|
611
|
+
MODEL_DB.reset
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
it "should return the first record where the primary key matches" do
|
|
615
|
+
@ds.with_pk(1).should == @c.load(:id=>1)
|
|
616
|
+
MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
it "should handle existing filters" do
|
|
620
|
+
@ds.filter(:a=>2).with_pk(1)
|
|
621
|
+
MODEL_DB.sqls.should == ["SELECT * FROM a WHERE ((a = 2) AND (a.id = 1)) LIMIT 1"]
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
it "should work with string values" do
|
|
625
|
+
@ds.with_pk("foo")
|
|
626
|
+
MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 'foo') LIMIT 1"]
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
it "should handle an array for composite primary keys" do
|
|
630
|
+
@c.set_primary_key :id1, :id2
|
|
631
|
+
@ds.with_pk([1, 2])
|
|
632
|
+
sqls = MODEL_DB.sqls
|
|
633
|
+
["SELECT * FROM a WHERE ((a.id1 = 1) AND (a.id2 = 2)) LIMIT 1",
|
|
634
|
+
"SELECT * FROM a WHERE ((a.id2 = 2) AND (a.id1 = 1)) LIMIT 1"].should include(sqls.pop)
|
|
635
|
+
sqls.should == []
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
it "should have #[] consider an integer as a primary key lookup" do
|
|
639
|
+
@ds[1].should == @c.load(:id=>1)
|
|
640
|
+
MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
it "should not have #[] consider a string as a primary key lookup" do
|
|
644
|
+
@ds['foo'].should == @c.load(:id=>1)
|
|
645
|
+
MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (foo) LIMIT 1"]
|
|
486
646
|
end
|
|
487
647
|
end
|
|
@@ -3,39 +3,25 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
3
3
|
describe Sequel::Model::DatasetMethods, "#destroy" do
|
|
4
4
|
before do
|
|
5
5
|
@c = Class.new(Sequel::Model(:items)) do
|
|
6
|
-
|
|
6
|
+
self::Destroyed = []
|
|
7
7
|
def destroy
|
|
8
|
-
|
|
9
|
-
end
|
|
10
|
-
def self.destroyed
|
|
11
|
-
class_variable_get(:@@destroyed)
|
|
8
|
+
model::Destroyed << self
|
|
12
9
|
end
|
|
13
10
|
end
|
|
14
11
|
@d = @c.dataset
|
|
12
|
+
@d._fetch = [{:id=>1}, {:id=>2}]
|
|
15
13
|
MODEL_DB.reset
|
|
16
14
|
end
|
|
17
15
|
|
|
18
16
|
it "should instantiate objects in the dataset and call destroy on each" do
|
|
19
|
-
def @d.fetch_rows(sql)
|
|
20
|
-
yield({:id=>1})
|
|
21
|
-
yield({:id=>2})
|
|
22
|
-
end
|
|
23
17
|
@d.destroy
|
|
24
|
-
@c.
|
|
18
|
+
@c::Destroyed.collect{|x| x.values}.should == [{:id=>1}, {:id=>2}]
|
|
25
19
|
end
|
|
26
20
|
|
|
27
21
|
it "should return the number of records destroyed" do
|
|
28
|
-
def @d.fetch_rows(sql)
|
|
29
|
-
yield({:id=>1})
|
|
30
|
-
yield({:id=>2})
|
|
31
|
-
end
|
|
32
22
|
@d.destroy.should == 2
|
|
33
|
-
|
|
34
|
-
yield({:id=>1})
|
|
35
|
-
end
|
|
23
|
+
@d._fetch = [[{:i=>1}], []]
|
|
36
24
|
@d.destroy.should == 1
|
|
37
|
-
def @d.fetch_rows(sql)
|
|
38
|
-
end
|
|
39
25
|
@d.destroy.should == 0
|
|
40
26
|
end
|
|
41
27
|
|
|
@@ -61,10 +47,7 @@ describe Sequel::Model::DatasetMethods, "#to_hash" do
|
|
|
61
47
|
end
|
|
62
48
|
|
|
63
49
|
it "should result in a hash with primary key value keys and model object values" do
|
|
64
|
-
|
|
65
|
-
yield({:name=>1})
|
|
66
|
-
yield({:name=>2})
|
|
67
|
-
end
|
|
50
|
+
@d._fetch = [{:name=>1}, {:name=>2}]
|
|
68
51
|
h = @d.to_hash
|
|
69
52
|
h.should be_a_kind_of(Hash)
|
|
70
53
|
a = h.to_a
|
|
@@ -73,10 +56,7 @@ describe Sequel::Model::DatasetMethods, "#to_hash" do
|
|
|
73
56
|
end
|
|
74
57
|
|
|
75
58
|
it "should result in a hash with given value keys and model object values" do
|
|
76
|
-
|
|
77
|
-
yield({:name=>1, :number=>3})
|
|
78
|
-
yield({:name=>2, :number=>4})
|
|
79
|
-
end
|
|
59
|
+
@d._fetch = [{:name=>1, :number=>3}, {:name=>2, :number=>4}]
|
|
80
60
|
h = @d.to_hash(:number)
|
|
81
61
|
h.should be_a_kind_of(Hash)
|
|
82
62
|
a = h.to_a
|