sequel 1.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +127 -0
- data/COPYING +1 -0
- data/README +5 -4
- data/Rakefile +78 -25
- data/lib/sequel.rb +1 -2
- data/lib/sequel_model.rb +324 -0
- data/lib/sequel_model/associations.rb +351 -0
- data/lib/sequel_model/base.rb +120 -0
- data/lib/sequel_model/caching.rb +42 -0
- data/lib/sequel_model/eager_loading.rb +169 -0
- data/lib/sequel_model/hooks.rb +55 -0
- data/lib/sequel_model/plugins.rb +47 -0
- data/lib/sequel_model/pretty_table.rb +73 -0
- data/lib/sequel_model/record.rb +336 -0
- data/lib/sequel_model/schema.rb +48 -0
- data/lib/sequel_model/validations.rb +15 -0
- data/spec/associations_spec.rb +712 -0
- data/spec/base_spec.rb +239 -0
- data/spec/caching_spec.rb +150 -0
- data/spec/deprecated_relations_spec.rb +153 -0
- data/spec/eager_loading_spec.rb +260 -0
- data/spec/hooks_spec.rb +269 -0
- data/spec/model_spec.rb +543 -0
- data/spec/plugins_spec.rb +74 -0
- data/spec/rcov.opts +4 -0
- data/spec/record_spec.rb +593 -0
- data/spec/schema_spec.rb +69 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/validations_spec.rb +246 -0
- metadata +90 -56
@@ -0,0 +1,260 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe Sequel::Model, "eager" do
|
4
|
+
before(:each) do
|
5
|
+
MODEL_DB.reset
|
6
|
+
|
7
|
+
class EagerAlbum < Sequel::Model(:albums)
|
8
|
+
def columns; [:id, :band_id]; end
|
9
|
+
many_to_one :band, :class=>'EagerBand', :key=>:band_id
|
10
|
+
one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id
|
11
|
+
many_to_many :genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag
|
12
|
+
end
|
13
|
+
|
14
|
+
class EagerBand < Sequel::Model(:bands)
|
15
|
+
def columns; [:id]; end
|
16
|
+
one_to_many :albums, :class=>'EagerAlbum', :key=>:band_id, :eager=>:tracks
|
17
|
+
many_to_many :members, :class=>'EagerBandMember', :left_key=>:band_id, :right_key=>:member_id, :join_table=>:bm
|
18
|
+
end
|
19
|
+
|
20
|
+
class EagerTrack < Sequel::Model(:tracks)
|
21
|
+
def columns; [:id, :album_id]; end
|
22
|
+
many_to_one :album, :class=>'EagerAlbum', :key=>:album_id
|
23
|
+
end
|
24
|
+
|
25
|
+
class EagerGenre < Sequel::Model(:genres)
|
26
|
+
def columns; [:id]; end
|
27
|
+
many_to_many :albums, :class=>'EagerAlbum', :left_key=>:genre_id, :right_key=>:album_id, :join_table=>:ag
|
28
|
+
end
|
29
|
+
|
30
|
+
class EagerBandMember < Sequel::Model(:members)
|
31
|
+
def columns; [:id]; end
|
32
|
+
many_to_many :bands, :class=>'EagerBand', :left_key=>:member_id, :right_key=>:band_id, :join_table=>:bm, :order =>:id
|
33
|
+
end
|
34
|
+
|
35
|
+
EagerAlbum.dataset.extend(Module.new {
|
36
|
+
def fetch_rows(sql)
|
37
|
+
h = {:id => 1, :band_id=> 2}
|
38
|
+
h.merge!(:x_foreign_key_x=>4) if sql =~ /ag\.genre_id/
|
39
|
+
@db << sql
|
40
|
+
yield h
|
41
|
+
end
|
42
|
+
})
|
43
|
+
|
44
|
+
EagerBand.dataset.extend(Module.new {
|
45
|
+
def fetch_rows(sql)
|
46
|
+
h = {:id => 2}
|
47
|
+
h.merge!(:x_foreign_key_x=>5) if sql =~ /bm\.member_id/
|
48
|
+
@db << sql
|
49
|
+
yield h
|
50
|
+
end
|
51
|
+
})
|
52
|
+
|
53
|
+
EagerTrack.dataset.extend(Module.new {
|
54
|
+
def fetch_rows(sql)
|
55
|
+
@db << sql
|
56
|
+
yield({:id => 3, :album_id => 1})
|
57
|
+
end
|
58
|
+
})
|
59
|
+
|
60
|
+
EagerGenre.dataset.extend(Module.new {
|
61
|
+
def fetch_rows(sql)
|
62
|
+
h = {:id => 4}
|
63
|
+
h.merge!(:x_foreign_key_x=>1) if sql =~ /ag\.album_id/
|
64
|
+
@db << sql
|
65
|
+
yield h
|
66
|
+
end
|
67
|
+
})
|
68
|
+
|
69
|
+
EagerBandMember.dataset.extend(Module.new {
|
70
|
+
def fetch_rows(sql)
|
71
|
+
h = {:id => 5}
|
72
|
+
h.merge!(:x_foreign_key_x=>2) if sql =~ /bm\.band_id/
|
73
|
+
@db << sql
|
74
|
+
yield h
|
75
|
+
end
|
76
|
+
})
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should eagerly load a single many_to_one association" do
|
80
|
+
a = EagerAlbum.eager(:band).all
|
81
|
+
a.should be_a_kind_of(Array)
|
82
|
+
a.size.should == 1
|
83
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
84
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
85
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM bands WHERE (id IN (2))']
|
86
|
+
a = a.first
|
87
|
+
a.band.should be_a_kind_of(EagerBand)
|
88
|
+
a.band.values.should == {:id => 2}
|
89
|
+
MODEL_DB.sqls.length.should == 2
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should eagerly load a single one_to_many association" do
|
93
|
+
a = EagerAlbum.eager(:tracks).all
|
94
|
+
a.should be_a_kind_of(Array)
|
95
|
+
a.size.should == 1
|
96
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
97
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
98
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (album_id IN (1))']
|
99
|
+
a = a.first
|
100
|
+
a.tracks.should be_a_kind_of(Array)
|
101
|
+
a.tracks.size.should == 1
|
102
|
+
a.tracks.first.should be_a_kind_of(EagerTrack)
|
103
|
+
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
104
|
+
MODEL_DB.sqls.length.should == 2
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should eagerly load a single many_to_many association" do
|
108
|
+
a = EagerAlbum.eager(:genres).all
|
109
|
+
a.should be_a_kind_of(Array)
|
110
|
+
a.size.should == 1
|
111
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
112
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
113
|
+
MODEL_DB.sqls.length.should == 2
|
114
|
+
MODEL_DB.sqls[0].should == 'SELECT * FROM albums'
|
115
|
+
["SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) AND (ag.album_id IN (1))",
|
116
|
+
"SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.album_id IN (1)) AND (ag.genre_id = genres.id)"
|
117
|
+
].should(include(MODEL_DB.sqls[1]))
|
118
|
+
a = a.first
|
119
|
+
a.genres.should be_a_kind_of(Array)
|
120
|
+
a.genres.size.should == 1
|
121
|
+
a.genres.first.should be_a_kind_of(EagerGenre)
|
122
|
+
a.genres.first.values.should == {:id => 4}
|
123
|
+
MODEL_DB.sqls.length.should == 2
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should eagerly load multiple associations" do
|
127
|
+
a = EagerAlbum.eager(:genres, :tracks, :band).all
|
128
|
+
a.should be_a_kind_of(Array)
|
129
|
+
a.size.should == 1
|
130
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
131
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
132
|
+
MODEL_DB.sqls.length.should == 4
|
133
|
+
MODEL_DB.sqls[0].should == 'SELECT * FROM albums'
|
134
|
+
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM bands WHERE (id IN (2))'))
|
135
|
+
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM tracks WHERE (album_id IN (1))'))
|
136
|
+
sqls = MODEL_DB.sqls[1..-1] - ['SELECT * FROM bands WHERE (id IN (2))', 'SELECT * FROM tracks WHERE (album_id IN (1))']
|
137
|
+
["SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) AND (ag.album_id IN (1))",
|
138
|
+
"SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.album_id IN (1)) AND (ag.genre_id = genres.id)"
|
139
|
+
].should(include(sqls[0]))
|
140
|
+
a = a.first
|
141
|
+
a.band.should be_a_kind_of(EagerBand)
|
142
|
+
a.band.values.should == {:id => 2}
|
143
|
+
a.tracks.should be_a_kind_of(Array)
|
144
|
+
a.tracks.size.should == 1
|
145
|
+
a.tracks.first.should be_a_kind_of(EagerTrack)
|
146
|
+
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
147
|
+
a.genres.should be_a_kind_of(Array)
|
148
|
+
a.genres.size.should == 1
|
149
|
+
a.genres.first.should be_a_kind_of(EagerGenre)
|
150
|
+
a.genres.first.values.should == {:id => 4}
|
151
|
+
MODEL_DB.sqls.length.should == 4
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should allow cascading of eager loading for associations of associated models" do
|
155
|
+
a = EagerTrack.eager(:album=>{:band=>:members}).all
|
156
|
+
a.should be_a_kind_of(Array)
|
157
|
+
a.size.should == 1
|
158
|
+
a.first.should be_a_kind_of(EagerTrack)
|
159
|
+
a.first.values.should == {:id => 3, :album_id => 1}
|
160
|
+
MODEL_DB.sqls.length.should == 4
|
161
|
+
MODEL_DB.sqls[0...-1].should == ['SELECT * FROM tracks',
|
162
|
+
'SELECT * FROM albums WHERE (id IN (1))',
|
163
|
+
'SELECT * FROM bands WHERE (id IN (2))']
|
164
|
+
["SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON (bm.member_id = members.id) AND (bm.band_id IN (2))",
|
165
|
+
"SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON (bm.band_id IN (2)) AND (bm.member_id = members.id)"
|
166
|
+
].should(include(MODEL_DB.sqls[-1]))
|
167
|
+
a = a.first
|
168
|
+
a.album.should be_a_kind_of(EagerAlbum)
|
169
|
+
a.album.values.should == {:id => 1, :band_id => 2}
|
170
|
+
a.album.band.should be_a_kind_of(EagerBand)
|
171
|
+
a.album.band.values.should == {:id => 2}
|
172
|
+
a.album.band.members.should be_a_kind_of(Array)
|
173
|
+
a.album.band.members.size.should == 1
|
174
|
+
a.album.band.members.first.should be_a_kind_of(EagerBandMember)
|
175
|
+
a.album.band.members.first.values.should == {:id => 5}
|
176
|
+
MODEL_DB.sqls.length.should == 4
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should cascade eagerly loading when the :eager association option is used" do
|
180
|
+
a = EagerBand.eager(:albums).all
|
181
|
+
a.should be_a_kind_of(Array)
|
182
|
+
a.size.should == 1
|
183
|
+
a.first.should be_a_kind_of(EagerBand)
|
184
|
+
a.first.values.should == {:id => 2}
|
185
|
+
MODEL_DB.sqls.should == ['SELECT * FROM bands',
|
186
|
+
'SELECT * FROM albums WHERE (band_id IN (2))',
|
187
|
+
'SELECT * FROM tracks WHERE (album_id IN (1))']
|
188
|
+
a = a.first
|
189
|
+
a.albums.should be_a_kind_of(Array)
|
190
|
+
a.albums.size.should == 1
|
191
|
+
a.albums.first.should be_a_kind_of(EagerAlbum)
|
192
|
+
a.albums.first.values.should == {:id => 1, :band_id => 2}
|
193
|
+
a = a.albums.first
|
194
|
+
a.tracks.should be_a_kind_of(Array)
|
195
|
+
a.tracks.size.should == 1
|
196
|
+
a.tracks.first.should be_a_kind_of(EagerTrack)
|
197
|
+
a.tracks.first.values.should == {:id => 3, :album_id => 1}
|
198
|
+
MODEL_DB.sqls.length.should == 3
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should respect :eager when lazily loading an association" do
|
202
|
+
a = EagerBand.all
|
203
|
+
a.should be_a_kind_of(Array)
|
204
|
+
a.size.should == 1
|
205
|
+
a.first.should be_a_kind_of(EagerBand)
|
206
|
+
a.first.values.should == {:id => 2}
|
207
|
+
MODEL_DB.sqls.should == ['SELECT * FROM bands']
|
208
|
+
a = a.first
|
209
|
+
a.albums.all
|
210
|
+
MODEL_DB.sqls.should == ['SELECT * FROM bands',
|
211
|
+
'SELECT * FROM albums WHERE (band_id = 2)',
|
212
|
+
'SELECT * FROM tracks WHERE (album_id IN (1))']
|
213
|
+
a.albums.should be_a_kind_of(Array)
|
214
|
+
a.albums.size.should == 1
|
215
|
+
a.albums.first.should be_a_kind_of(EagerAlbum)
|
216
|
+
a.albums.first.values.should == {:id => 1, :band_id => 2}
|
217
|
+
a = a.albums.first
|
218
|
+
a.tracks.should be_a_kind_of(Array)
|
219
|
+
a.tracks.size.should == 1
|
220
|
+
a.tracks.first.should be_a_kind_of(EagerTrack)
|
221
|
+
a.tracks.first.values.should == {:id => 3, :album_id => 1}
|
222
|
+
MODEL_DB.sqls.length.should == 3
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should respect :order when eagerly loading" do
|
226
|
+
a = EagerBandMember.eager(:bands).all
|
227
|
+
a.should be_a_kind_of(Array)
|
228
|
+
a.size.should == 1
|
229
|
+
a.first.should be_a_kind_of(EagerBandMember)
|
230
|
+
a.first.values.should == {:id => 5}
|
231
|
+
MODEL_DB.sqls.length.should == 2
|
232
|
+
MODEL_DB.sqls[0].should == 'SELECT * FROM members'
|
233
|
+
['SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON (bm.band_id = bands.id) AND (bm.member_id IN (5)) ORDER BY id',
|
234
|
+
'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON (bm.member_id IN (5)) AND (bm.band_id = bands.id) ORDER BY id'
|
235
|
+
].should(include(MODEL_DB.sqls[1]))
|
236
|
+
a = a.first
|
237
|
+
a.bands.should be_a_kind_of(Array)
|
238
|
+
a.bands.size.should == 1
|
239
|
+
a.bands.first.should be_a_kind_of(EagerBand)
|
240
|
+
a.bands.first.values.should == {:id => 2}
|
241
|
+
MODEL_DB.sqls.length.should == 2
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should populate the reciprocal many_to_one association when eagerly loading the one_to_many association" do
|
245
|
+
a = EagerAlbum.eager(:tracks).all
|
246
|
+
a.should be_a_kind_of(Array)
|
247
|
+
a.size.should == 1
|
248
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
249
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
250
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM tracks WHERE (album_id IN (1))']
|
251
|
+
a = a.first
|
252
|
+
a.tracks.should be_a_kind_of(Array)
|
253
|
+
a.tracks.size.should == 1
|
254
|
+
a.tracks.first.should be_a_kind_of(EagerTrack)
|
255
|
+
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
256
|
+
a.tracks.first.album.should be_a_kind_of(EagerAlbum)
|
257
|
+
a.tracks.first.album.should == a
|
258
|
+
MODEL_DB.sqls.length.should == 2
|
259
|
+
end
|
260
|
+
end
|
data/spec/hooks_spec.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "Model hooks" do
|
4
|
+
before do
|
5
|
+
MODEL_DB.reset
|
6
|
+
|
7
|
+
@hooks = [
|
8
|
+
:after_initialize,
|
9
|
+
:before_create,
|
10
|
+
:after_create,
|
11
|
+
:before_update,
|
12
|
+
:after_update,
|
13
|
+
:before_save,
|
14
|
+
:after_save,
|
15
|
+
:before_destroy,
|
16
|
+
:after_destroy
|
17
|
+
]
|
18
|
+
|
19
|
+
# @hooks.each {|h| Sequel::Model.class_def(h) {}}
|
20
|
+
end
|
21
|
+
|
22
|
+
specify "should be definable using def <hook name>" do
|
23
|
+
c = Class.new(Sequel::Model) do
|
24
|
+
def before_save
|
25
|
+
"hi there"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
c.new.before_save.should == 'hi there'
|
30
|
+
end
|
31
|
+
|
32
|
+
specify "should be definable using a block" do
|
33
|
+
$adds = []
|
34
|
+
c = Class.new(Sequel::Model) do
|
35
|
+
before_save {$adds << 'hi'}
|
36
|
+
end
|
37
|
+
|
38
|
+
c.new.before_save
|
39
|
+
$adds.should == ['hi']
|
40
|
+
end
|
41
|
+
|
42
|
+
specify "should be definable using a method name" do
|
43
|
+
$adds = []
|
44
|
+
c = Class.new(Sequel::Model) do
|
45
|
+
def bye; $adds << 'bye'; end
|
46
|
+
before_save :bye
|
47
|
+
end
|
48
|
+
|
49
|
+
c.new.before_save
|
50
|
+
$adds.should == ['bye']
|
51
|
+
end
|
52
|
+
|
53
|
+
specify "should be additive" do
|
54
|
+
$adds = []
|
55
|
+
c = Class.new(Sequel::Model) do
|
56
|
+
before_save {$adds << 'hyiyie'}
|
57
|
+
before_save {$adds << 'byiyie'}
|
58
|
+
end
|
59
|
+
|
60
|
+
c.new.before_save
|
61
|
+
$adds.should == ['hyiyie', 'byiyie']
|
62
|
+
end
|
63
|
+
|
64
|
+
specify "should be inheritable" do
|
65
|
+
# pending
|
66
|
+
|
67
|
+
$adds = []
|
68
|
+
a = Class.new(Sequel::Model) do
|
69
|
+
before_save {$adds << '123'}
|
70
|
+
end
|
71
|
+
|
72
|
+
b = Class.new(a) do
|
73
|
+
before_save {$adds << '456'}
|
74
|
+
before_save {$adds << '789'}
|
75
|
+
end
|
76
|
+
|
77
|
+
b.new.before_save
|
78
|
+
$adds.should == ['123', '456', '789']
|
79
|
+
end
|
80
|
+
|
81
|
+
specify "should be overridable in descendant classes" do
|
82
|
+
$adds = []
|
83
|
+
a = Class.new(Sequel::Model) do
|
84
|
+
before_save {$adds << '123'}
|
85
|
+
end
|
86
|
+
|
87
|
+
b = Class.new(a) do
|
88
|
+
def before_save; $adds << '456'; end
|
89
|
+
end
|
90
|
+
|
91
|
+
a.new.before_save
|
92
|
+
$adds.should == ['123']
|
93
|
+
$adds = []
|
94
|
+
b.new.before_save
|
95
|
+
$adds.should == ['456']
|
96
|
+
end
|
97
|
+
|
98
|
+
specify "should stop processing if a hook returns false" do
|
99
|
+
$flag = true
|
100
|
+
$adds = []
|
101
|
+
|
102
|
+
a = Class.new(Sequel::Model) do
|
103
|
+
before_save {$adds << 'blah'; $flag}
|
104
|
+
before_save {$adds << 'cruel'}
|
105
|
+
end
|
106
|
+
|
107
|
+
a.new.before_save
|
108
|
+
$adds.should == ['blah', 'cruel']
|
109
|
+
|
110
|
+
# chain should not break on nil
|
111
|
+
$adds = []
|
112
|
+
$flag = nil
|
113
|
+
a.new.before_save
|
114
|
+
$adds.should == ['blah', 'cruel']
|
115
|
+
|
116
|
+
$adds = []
|
117
|
+
$flag = false
|
118
|
+
a.new.before_save
|
119
|
+
$adds.should == ['blah']
|
120
|
+
|
121
|
+
b = Class.new(a) do
|
122
|
+
before_save {$adds << 'mau'}
|
123
|
+
end
|
124
|
+
|
125
|
+
$adds = []
|
126
|
+
b.new.before_save
|
127
|
+
$adds.should == ['blah']
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "Model#after_initialize" do
|
132
|
+
specify "should be called after initialization" do
|
133
|
+
$values1 = nil
|
134
|
+
|
135
|
+
a = Class.new(Sequel::Model) do
|
136
|
+
after_initialize do
|
137
|
+
$values1 = @values.clone
|
138
|
+
raise Sequel::Error if @values[:blow]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
a.new(:x => 1, :y => 2)
|
143
|
+
$values1.should == {:x => 1, :y => 2}
|
144
|
+
|
145
|
+
proc {a.new(:blow => true)}.should raise_error(Sequel::Error)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "Model#before_create && Model#after_create" do
|
150
|
+
setup do
|
151
|
+
MODEL_DB.reset
|
152
|
+
|
153
|
+
@c = Class.new(Sequel::Model(:items)) do
|
154
|
+
no_primary_key
|
155
|
+
|
156
|
+
before_create {MODEL_DB << "BLAH before"}
|
157
|
+
after_create {MODEL_DB << "BLAH after"}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
specify "should be called around new record creation" do
|
162
|
+
@c.create(:x => 2)
|
163
|
+
MODEL_DB.sqls.should == [
|
164
|
+
'BLAH before',
|
165
|
+
'INSERT INTO items (x) VALUES (2)',
|
166
|
+
'BLAH after'
|
167
|
+
]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "Model#before_update && Model#after_update" do
|
172
|
+
setup do
|
173
|
+
MODEL_DB.reset
|
174
|
+
|
175
|
+
@c = Class.new(Sequel::Model(:items)) do
|
176
|
+
before_update {MODEL_DB << "BLAH before"}
|
177
|
+
after_update {MODEL_DB << "BLAH after"}
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
specify "should be called around record update" do
|
182
|
+
m = @c.load(:id => 2233)
|
183
|
+
m.save
|
184
|
+
MODEL_DB.sqls.should == [
|
185
|
+
'BLAH before',
|
186
|
+
'UPDATE items SET id = 2233 WHERE (id = 2233)',
|
187
|
+
'BLAH after'
|
188
|
+
]
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe "Model#before_save && Model#after_save" do
|
193
|
+
setup do
|
194
|
+
MODEL_DB.reset
|
195
|
+
|
196
|
+
@c = Class.new(Sequel::Model(:items)) do
|
197
|
+
before_save {MODEL_DB << "BLAH before"}
|
198
|
+
after_save {MODEL_DB << "BLAH after"}
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
specify "should be called around record update" do
|
203
|
+
m = @c.load(:id => 2233)
|
204
|
+
m.save
|
205
|
+
MODEL_DB.sqls.should == [
|
206
|
+
'BLAH before',
|
207
|
+
'UPDATE items SET id = 2233 WHERE (id = 2233)',
|
208
|
+
'BLAH after'
|
209
|
+
]
|
210
|
+
end
|
211
|
+
|
212
|
+
specify "should be called around record creation" do
|
213
|
+
@c.no_primary_key
|
214
|
+
@c.create(:x => 2)
|
215
|
+
MODEL_DB.sqls.should == [
|
216
|
+
'BLAH before',
|
217
|
+
'INSERT INTO items (x) VALUES (2)',
|
218
|
+
'BLAH after'
|
219
|
+
]
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "Model#before_destroy && Model#after_destroy" do
|
224
|
+
setup do
|
225
|
+
MODEL_DB.reset
|
226
|
+
|
227
|
+
@c = Class.new(Sequel::Model(:items)) do
|
228
|
+
before_destroy {MODEL_DB << "BLAH before"}
|
229
|
+
after_destroy {MODEL_DB << "BLAH after"}
|
230
|
+
|
231
|
+
def delete
|
232
|
+
MODEL_DB << "DELETE BLAH"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
specify "should be called around record update" do
|
238
|
+
m = @c.new(:id => 2233)
|
239
|
+
m.destroy
|
240
|
+
MODEL_DB.sqls.should == [
|
241
|
+
'BLAH before',
|
242
|
+
'DELETE BLAH',
|
243
|
+
'BLAH after'
|
244
|
+
]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
describe "Model#has_hooks?" do
|
249
|
+
setup do
|
250
|
+
@c = Class.new(Sequel::Model)
|
251
|
+
end
|
252
|
+
|
253
|
+
specify "should return false if no hooks are defined" do
|
254
|
+
@c.has_hooks?(:before_save).should be_false
|
255
|
+
end
|
256
|
+
|
257
|
+
specify "should return true if hooks are defined" do
|
258
|
+
@c.before_save {'blah'}
|
259
|
+
@c.has_hooks?(:before_save).should be_true
|
260
|
+
end
|
261
|
+
|
262
|
+
specify "should return true if hooks are inherited" do
|
263
|
+
@d = Class.new(@c)
|
264
|
+
@d.has_hooks?(:before_save).should be_false
|
265
|
+
|
266
|
+
@c.before_save :blah
|
267
|
+
@d.has_hooks?(:before_save).should be_true
|
268
|
+
end
|
269
|
+
end
|