sequel 1.3 → 1.4.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 +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
|