sequel 0.4.4.2 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ module Sequel::Plugins
2
+
3
+ module Timestamped
4
+ def self.apply(m, opts)
5
+ m.class_def(:get_stamp) {@values[:stamp]}
6
+ m.meta_def(:stamp_opts) {opts}
7
+ m.before_save {@values[:stamp] = Time.now}
8
+ end
9
+
10
+ module InstanceMethods
11
+ def abc; timestamped_opts; end
12
+ end
13
+
14
+ module ClassMethods
15
+ def deff; timestamped_opts; end
16
+ end
17
+
18
+ # ??
19
+ # module DatasetMethods
20
+ # def ghi; timestamped_opts; end
21
+ # end
22
+ end
23
+
24
+ end
25
+
26
+ describe Sequel::Model, "using a plugin" do
27
+
28
+ it "should fail if the plugin is not found" do
29
+ proc do
30
+ c = Class.new(Sequel::Model) do
31
+ is :something_or_other
32
+ end
33
+ end.should raise_error(LoadError)
34
+ end
35
+
36
+ it "should apply the plugin to the class" do
37
+ c = nil
38
+ proc do
39
+ c = Class.new(Sequel::Model) do
40
+ is :timestamped, :a => 1, :b => 2
41
+ end
42
+ end.should_not raise_error(LoadError)
43
+
44
+ c.should respond_to(:stamp_opts)
45
+ c.stamp_opts.should == {:a => 1, :b => 2}
46
+
47
+ m = c.new
48
+ m.should respond_to(:get_stamp)
49
+ m.should respond_to(:abc)
50
+ m.abc.should == {:a => 1, :b => 2}
51
+ t = Time.now
52
+ m[:stamp] = t
53
+ m.get_stamp.should == t
54
+
55
+ c.should respond_to(:deff)
56
+ c.deff.should == {:a => 1, :b => 2}
57
+ end
58
+
59
+ end
@@ -0,0 +1,360 @@
1
+ describe "Model#save" do
2
+
3
+ before(:each) do
4
+ MODEL_DB.reset
5
+
6
+ @c = Class.new(Sequel::Model(:items)) do
7
+ def columns
8
+ [:id, :x, :y]
9
+ end
10
+ end
11
+ end
12
+
13
+ it "should insert a record for a new model instance" do
14
+ o = @c.new(:x => 1)
15
+ o.save
16
+
17
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
18
+ end
19
+
20
+ it "should update a record for an existing model instance" do
21
+ o = @c.new(:id => 3, :x => 1)
22
+ o.save
23
+
24
+ MODEL_DB.sqls.first.should =~
25
+ /UPDATE items SET (id = 3, x = 1|x = 1, id = 3) WHERE \(id = 3\)/
26
+ end
27
+
28
+ it "should update only the given columns if given" do
29
+ o = @c.new(:id => 3, :x => 1, :y => nil)
30
+ o.save(:y)
31
+
32
+ MODEL_DB.sqls.first.should == "UPDATE items SET y = NULL WHERE (id = 3)"
33
+ end
34
+
35
+ it "should mark saved columns as not changed" do
36
+ o = @c.new(:id => 3, :x => 1, :y => nil)
37
+ o[:y] = 4
38
+ o.changed_columns.should == [:y]
39
+ o.save(:x)
40
+ o.changed_columns.should == [:y]
41
+ o.save(:y)
42
+ o.changed_columns.should == []
43
+ end
44
+
45
+ end
46
+
47
+ describe "Model#save_changes" do
48
+
49
+ before(:each) do
50
+ MODEL_DB.reset
51
+
52
+ @c = Class.new(Sequel::Model(:items)) do
53
+ def columns
54
+ [:id, :x, :y]
55
+ end
56
+ end
57
+ end
58
+
59
+ it "should do nothing if no changed columns" do
60
+ o = @c.new(:id => 3, :x => 1, :y => nil)
61
+ o.save_changes
62
+
63
+ MODEL_DB.sqls.should be_empty
64
+ end
65
+
66
+ it "should update only changed columns" do
67
+ o = @c.new(:id => 3, :x => 1, :y => nil)
68
+ o.x = 2
69
+
70
+ o.save_changes
71
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
72
+ o.save_changes
73
+ o.save_changes
74
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
75
+ MODEL_DB.reset
76
+
77
+ o.y = 4
78
+ o.save_changes
79
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
80
+ o.save_changes
81
+ o.save_changes
82
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
83
+ end
84
+
85
+ end
86
+
87
+ describe "Model#set" do
88
+
89
+ before(:each) do
90
+ MODEL_DB.reset
91
+
92
+ @c = Class.new(Sequel::Model(:items)) do
93
+ def columns
94
+ [:id, :x, :y]
95
+ end
96
+ end
97
+ end
98
+
99
+ it "should generate an update statement" do
100
+ o = @c.new(:id => 1)
101
+ o.set(:x => 1)
102
+ MODEL_DB.sqls.first.should == "UPDATE items SET x = 1 WHERE (id = 1)"
103
+ end
104
+
105
+ it "should update attribute values" do
106
+ o = @c.new(:id => 1)
107
+ o.x.should be_nil
108
+ o.set(:x => 1)
109
+ o.x.should == 1
110
+ end
111
+
112
+ it "should be aliased by #update" do
113
+ o = @c.new(:id => 1)
114
+ o.update(:x => 1)
115
+ MODEL_DB.sqls.first.should == "UPDATE items SET x = 1 WHERE (id = 1)"
116
+ end
117
+ end
118
+
119
+
120
+ describe "Model#new?" do
121
+
122
+ before(:each) do
123
+ MODEL_DB.reset
124
+
125
+ @c = Class.new(Sequel::Model(:items)) do
126
+ end
127
+ end
128
+
129
+ it "should be true for a new instance" do
130
+ n = @c.new(:x => 1)
131
+ n.should be_new
132
+ end
133
+
134
+ it "should be false after saving" do
135
+ n = @c.new(:x => 1)
136
+ n.save
137
+ n.should_not be_new
138
+ end
139
+
140
+ it "should alias new_record? to new?" do
141
+ n = @c.new(:x => 1)
142
+ n.should respond_to(:new_record?)
143
+ n.should be_new_record
144
+ n.save
145
+ n.should_not be_new_record
146
+ end
147
+
148
+ end
149
+
150
+ describe Sequel::Model, "w/ primary key" do
151
+
152
+ it "should default to ':id'" do
153
+ model_a = Class.new Sequel::Model
154
+ model_a.primary_key.should be_equal(:id)
155
+ end
156
+
157
+ it "should be changed through 'set_primary_key'" do
158
+ model_a = Class.new(Sequel::Model) { set_primary_key :a }
159
+ model_a.primary_key.should be_equal(:a)
160
+ end
161
+
162
+ it "should support multi argument composite keys" do
163
+ model_a = Class.new(Sequel::Model) { set_primary_key :a, :b }
164
+ model_a.primary_key.should be_eql([:a, :b])
165
+ end
166
+
167
+ it "should accept single argument composite keys" do
168
+ model_a = Class.new(Sequel::Model) { set_primary_key [:a, :b] }
169
+ model_a.primary_key.should be_eql([:a, :b])
170
+ end
171
+
172
+ end
173
+
174
+ describe Sequel::Model, "w/o primary key" do
175
+ it "should return nil for primary key" do
176
+ Class.new(Sequel::Model) { no_primary_key }.primary_key.should be_nil
177
+ end
178
+
179
+ it "should raise a Sequel::Error on 'this'" do
180
+ instance = Class.new(Sequel::Model) { no_primary_key }.new
181
+ proc { instance.this }.should raise_error(Sequel::Error)
182
+ end
183
+ end
184
+
185
+ describe Sequel::Model, "with this" do
186
+
187
+ before { @example = Class.new Sequel::Model(:examples) }
188
+
189
+ it "should return a dataset identifying the record" do
190
+ instance = @example.new :id => 3
191
+ instance.this.sql.should be_eql("SELECT * FROM examples WHERE (id = 3) LIMIT 1")
192
+ end
193
+
194
+ it "should support arbitary primary keys" do
195
+ @example.set_primary_key :a
196
+
197
+ instance = @example.new :a => 3
198
+ instance.this.sql.should be_eql("SELECT * FROM examples WHERE (a = 3) LIMIT 1")
199
+ end
200
+
201
+ it "should support composite primary keys" do
202
+ @example.set_primary_key :x, :y
203
+ instance = @example.new :x => 4, :y => 5
204
+
205
+ parts = [
206
+ 'SELECT * FROM examples WHERE %s LIMIT 1',
207
+ '(x = 4) AND (y = 5)',
208
+ '(y = 5) AND (x = 4)'
209
+ ].map { |expr| Regexp.escape expr }
210
+ regexp = Regexp.new parts.first % "(?:#{parts[1]}|#{parts[2]})"
211
+
212
+ instance.this.sql.should match(regexp)
213
+ end
214
+
215
+ end
216
+
217
+ describe "Model#pk" do
218
+
219
+ before(:each) do
220
+ @m = Class.new(Sequel::Model)
221
+ end
222
+
223
+ it "should be default return the value of the :id column" do
224
+ m = @m.new(:id => 111, :x => 2, :y => 3)
225
+ m.pk.should == 111
226
+ end
227
+
228
+ it "should be return the primary key value for custom primary key" do
229
+ @m.set_primary_key :x
230
+ m = @m.new(:id => 111, :x => 2, :y => 3)
231
+ m.pk.should == 2
232
+ end
233
+
234
+ it "should be return the primary key value for composite primary key" do
235
+ @m.set_primary_key [:y, :x]
236
+ m = @m.new(:id => 111, :x => 2, :y => 3)
237
+ m.pk.should == [3, 2]
238
+ end
239
+
240
+ it "should raise if no primary key" do
241
+ @m.set_primary_key nil
242
+ m = @m.new(:id => 111, :x => 2, :y => 3)
243
+ proc {m.pk}.should raise_error(Sequel::Error)
244
+
245
+ @m.no_primary_key
246
+ m = @m.new(:id => 111, :x => 2, :y => 3)
247
+ proc {m.pk}.should raise_error(Sequel::Error)
248
+ end
249
+
250
+ end
251
+
252
+ describe "Model#pk_hash" do
253
+
254
+ before(:each) do
255
+ @m = Class.new(Sequel::Model)
256
+ end
257
+
258
+ it "should be default return the value of the :id column" do
259
+ m = @m.new(:id => 111, :x => 2, :y => 3)
260
+ m.pk_hash.should == {:id => 111}
261
+ end
262
+
263
+ it "should be return the primary key value for custom primary key" do
264
+ @m.set_primary_key :x
265
+ m = @m.new(:id => 111, :x => 2, :y => 3)
266
+ m.pk_hash.should == {:x => 2}
267
+ end
268
+
269
+ it "should be return the primary key value for composite primary key" do
270
+ @m.set_primary_key [:y, :x]
271
+ m = @m.new(:id => 111, :x => 2, :y => 3)
272
+ m.pk_hash.should == {:y => 3, :x => 2}
273
+ end
274
+
275
+ it "should raise if no primary key" do
276
+ @m.set_primary_key nil
277
+ m = @m.new(:id => 111, :x => 2, :y => 3)
278
+ proc {m.pk_hash}.should raise_error(Sequel::Error)
279
+
280
+ @m.no_primary_key
281
+ m = @m.new(:id => 111, :x => 2, :y => 3)
282
+ proc {m.pk_hash}.should raise_error(Sequel::Error)
283
+ end
284
+ end
285
+
286
+ describe Sequel::Model, "create_with_params" do
287
+
288
+ before(:each) do
289
+ MODEL_DB.reset
290
+
291
+ @c = Class.new(Sequel::Model(:items)) do
292
+ def self.columns; [:x, :y]; end
293
+ end
294
+ end
295
+
296
+ it "should filter the given params using the model columns" do
297
+ @c.create_with_params(:x => 1, :z => 2)
298
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
299
+
300
+ MODEL_DB.reset
301
+ @c.create_with_params(:y => 1, :abc => 2)
302
+ MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
303
+ end
304
+
305
+ it "should be aliased by create_with" do
306
+ @c.create_with(:x => 1, :z => 2)
307
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
308
+
309
+ MODEL_DB.reset
310
+ @c.create_with(:y => 1, :abc => 2)
311
+ MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
312
+ end
313
+
314
+ end
315
+
316
+ describe Sequel::Model, "#destroy" do
317
+
318
+ before(:each) do
319
+ MODEL_DB.reset
320
+ @model = Class.new(Sequel::Model(:items))
321
+ @model.dataset.meta_def(:delete) {MODEL_DB.execute delete_sql}
322
+
323
+ @instance = @model.new(:id => 1234)
324
+ #@model.stub!(:delete).and_return(:true)
325
+ end
326
+
327
+ it "should run within a transaction" do
328
+ @model.db.should_receive(:transaction)
329
+ @instance.destroy
330
+ end
331
+
332
+ it "should run before_destroy and after_destroy hooks" do
333
+ @model.before_destroy {MODEL_DB.execute('before blah')}
334
+ @model.after_destroy {MODEL_DB.execute('after blah')}
335
+ @instance.destroy
336
+
337
+ MODEL_DB.sqls.should == [
338
+ "before blah",
339
+ "DELETE FROM items WHERE (id = 1234)",
340
+ "after blah"
341
+ ]
342
+ end
343
+ end
344
+
345
+ describe Sequel::Model, "#exists?" do
346
+
347
+ before(:each) do
348
+ @model = Class.new(Sequel::Model(:items))
349
+ @model_a = @model.new
350
+ end
351
+
352
+ it "should returns true when current instance exists" do
353
+ @model_a.exists?.should be_true
354
+ end
355
+
356
+ it "should return false when the current instance does not exist" do
357
+ pending("how would this be false?")
358
+ end
359
+
360
+ end
@@ -0,0 +1,148 @@
1
+ describe Sequel::Model, "one_to_one" do
2
+
3
+ before(:each) do
4
+ MODEL_DB.reset
5
+
6
+ @c1 = Class.new(Sequel::Model(:attributes)) do
7
+ end
8
+
9
+ @c2 = Class.new(Sequel::Model(:nodes)) do
10
+ end
11
+
12
+ @dataset = @c2.dataset
13
+
14
+ $sqls = []
15
+ @dataset.extend(Module.new {
16
+ def fetch_rows(sql)
17
+ $sqls << sql
18
+ yield({:hey => 1})
19
+ end
20
+
21
+ def update(values)
22
+ $sqls << update_sql(values)
23
+ end
24
+ }
25
+ )
26
+ end
27
+
28
+ it "should use implicit key if omitted" do
29
+ @c2.one_to_one :parent, :from => @c2
30
+
31
+ d = @c2.new(:id => 1, :parent_id => 234)
32
+ p = d.parent
33
+ p.class.should == @c2
34
+ p.values.should == {:hey => 1}
35
+
36
+ $sqls.should == ["SELECT * FROM nodes WHERE (id = 234) LIMIT 1"]
37
+ end
38
+
39
+ it "should use explicit key if given" do
40
+ @c2.one_to_one :parent, :from => @c2, :key => :blah
41
+
42
+ d = @c2.new(:id => 1, :blah => 567)
43
+ p = d.parent
44
+ p.class.should == @c2
45
+ p.values.should == {:hey => 1}
46
+
47
+ $sqls.should == ["SELECT * FROM nodes WHERE (id = 567) LIMIT 1"]
48
+ end
49
+
50
+ it "should support plain dataset in the from option" do
51
+ @c2.one_to_one :parent, :from => MODEL_DB[:xyz]
52
+
53
+ d = @c2.new(:id => 1, :parent_id => 789)
54
+ p = d.parent
55
+ p.class.should == Hash
56
+
57
+ MODEL_DB.sqls.should == ["SELECT * FROM xyz WHERE (id = 789) LIMIT 1"]
58
+ end
59
+
60
+ it "should support table name in the from option" do
61
+ @c2.one_to_one :parent, :from => :abc
62
+
63
+ d = @c2.new(:id => 1, :parent_id => 789)
64
+ p = d.parent
65
+ p.class.should == Hash
66
+
67
+ MODEL_DB.sqls.should == ["SELECT * FROM abc WHERE (id = 789) LIMIT 1"]
68
+ end
69
+
70
+ it "should return nil if key value is nil" do
71
+ @c2.one_to_one :parent, :from => @c2
72
+
73
+ d = @c2.new(:id => 1)
74
+ d.parent.should == nil
75
+ end
76
+
77
+ it "should define a setter method" do
78
+ @c2.one_to_one :parent, :from => @c2
79
+
80
+ d = @c2.new(:id => 1)
81
+ d.parent = {:id => 4321}
82
+ d.values.should == {:id => 1, :parent_id => 4321}
83
+ $sqls.last.should == "UPDATE nodes SET parent_id = 4321 WHERE (id = 1)"
84
+
85
+ d.parent = nil
86
+ d.values.should == {:id => 1, :parent_id => nil}
87
+ $sqls.last.should == "UPDATE nodes SET parent_id = NULL WHERE (id = 1)"
88
+
89
+ e = @c2.new(:id => 6677)
90
+ d.parent = e
91
+ d.values.should == {:id => 1, :parent_id => 6677}
92
+ $sqls.last.should == "UPDATE nodes SET parent_id = 6677 WHERE (id = 1)"
93
+ end
94
+
95
+ it "should warn with a depreciation notice if :class option was used" do
96
+ pending("write this spec")
97
+ end
98
+
99
+ end
100
+
101
+ describe Sequel::Model, "one_to_many" do
102
+
103
+ before(:each) do
104
+ MODEL_DB.reset
105
+
106
+ @c1 = Class.new(Sequel::Model(:attributes)) do
107
+ end
108
+
109
+ @c2 = Class.new(Sequel::Model(:nodes)) do
110
+ end
111
+ end
112
+
113
+ it "should define a getter method" do
114
+ @c2.one_to_many :attributes, :from => @c1, :key => :node_id
115
+
116
+ n = @c2.new(:id => 1234)
117
+ a = n.attributes
118
+ a.should be_a_kind_of(Sequel::Dataset)
119
+ a.sql.should == 'SELECT * FROM attributes WHERE (node_id = 1234)'
120
+ end
121
+
122
+ it "should support plain dataset in the from option" do
123
+ @c2.one_to_many :attributes, :from => MODEL_DB[:xyz], :key => :node_id
124
+
125
+ n = @c2.new(:id => 1234)
126
+ a = n.attributes
127
+ a.should be_a_kind_of(Sequel::Dataset)
128
+ a.sql.should == 'SELECT * FROM xyz WHERE (node_id = 1234)'
129
+ end
130
+
131
+ it "should support table name in the from option" do
132
+ @c2.one_to_many :attributes, :from => :abc, :key => :node_id
133
+
134
+ n = @c2.new(:id => 1234)
135
+ a = n.attributes
136
+ a.should be_a_kind_of(Sequel::Dataset)
137
+ a.sql.should == 'SELECT * FROM abc WHERE (node_id = 1234)'
138
+ end
139
+
140
+ it "should warn with a depreciation notice if :class option was used" do
141
+ pending("write this spec")
142
+ end
143
+
144
+ it "should warn with a depreciation notice if :on option was used" do
145
+ pending("write this spec")
146
+ end
147
+
148
+ end