@@ -166,19 +166,10 @@ def _one_time_conditions_valid_#{@callback_id}?
166
166
RUBY_EVAL
167
167
end
168
168
169
- # This will supply contents for before and around filters, and no
170
- # contents for after filters (for the forward pass).
171
- def start ( key = nil , object = nil )
172
- return if key && !object . send ( "_one_time_conditions_valid_#{ @callback_id } ?" )
173
-
174
- # options[0] is the compiled form of supplied conditions
175
- # options[1] is the "end" for the conditional
176
- #
169
+ # Wraps code with filter
170
+ def apply ( code , key = nil , object = nil )
177
171
case @kind
178
172
when :before
179
- # if condition # before_save :filter_name, :if => :condition
180
- # filter_name
181
- # end
182
173
<<-RUBY_EVAL
183
174
if !halted && #{ @compiled_options }
184
175
# This double assignment is to prevent warnings in 1.9.3 as
@@ -190,62 +181,64 @@ def start(key=nil, object=nil)
190
181
halted_callback_hook(#{ @raw_filter . inspect . inspect } )
191
182
end
192
183
end
184
+ #{ code }
193
185
RUBY_EVAL
194
- when :around
195
- # Compile around filters with conditions into proxy methods
196
- # that contain the conditions.
197
- #
198
- # For `around_save :filter_name, :if => :condition':
199
- #
200
- # def _conditional_callback_save_17
201
- # if condition
202
- # filter_name do
203
- # yield self
204
- # end
205
- # else
206
- # yield self
207
- # end
208
- # end
209
- #
210
- name = "_conditional_callback_#{ @kind } _#{ next_id } "
211
- @klass . class_eval <<-RUBY_EVAL , __FILE__ , __LINE__ + 1
212
- def #{ name } (halted)
213
- if #{ @compiled_options } && !halted
214
- #{ @filter } do
215
- yield self
216
- end
217
- else
218
- yield self
219
- end
220
- end
221
- RUBY_EVAL
222
- "#{ name } (halted) do"
223
- end
224
- end
225
-
226
- # This will supply contents for around and after filters, but not
227
- # before filters (for the backward pass).
228
- def end ( key = nil , object = nil )
229
- return if key && !object . send ( "_one_time_conditions_valid_#{ @callback_id } ?" )
230
-
231
- case @kind
232
186
when :after
233
- # after_save :filter_name, :if => :condition
234
187
<<-RUBY_EVAL
188
+ #{ code }
235
189
if #{ @compiled_options }
236
190
#{ @filter }
237
191
end
238
192
RUBY_EVAL
239
193
when :around
194
+ name = define_conditional_callback
240
195
<<-RUBY_EVAL
196
+ #{ name } (halted) do
197
+ #{ code }
241
198
value
242
199
end
243
200
RUBY_EVAL
244
201
end
245
202
end
246
203
204
+
205
+ def one_time_conditions_valid? ( object )
206
+ object . send ( "_one_time_conditions_valid_#{ @callback_id } ?" )
207
+ end
208
+
247
209
private
248
210
211
+ # Compile around filters with conditions into proxy methods
212
+ # that contain the conditions.
213
+ #
214
+ # For `around_save :filter_name, :if => :condition':
215
+ #
216
+ # def _conditional_callback_save_17
217
+ # if condition
218
+ # filter_name do
219
+ # yield self
220
+ # end
221
+ # else
222
+ # yield self
223
+ # end
224
+ # end
225
+ #
226
+ def define_conditional_callback
227
+ name = "_conditional_callback_#{ @kind } _#{ next_id } "
228
+ @klass . class_eval <<-RUBY_EVAL , __FILE__ , __LINE__ + 1
229
+ def #{ name } (halted)
230
+ if #{ @compiled_options } && !halted
231
+ #{ @filter } do
232
+ yield self
233
+ end
234
+ else
235
+ yield self
236
+ end
237
+ end
238
+ RUBY_EVAL
239
+ name
240
+ end
241
+
249
242
# Options support the same options as filters themselves (and support
250
243
# symbols, string, procs, and objects), so compile a conditional
251
244
# expression based on the options
@@ -348,10 +341,20 @@ def compile(key=nil, object=nil)
348
341
method << "value = nil"
349
342
method << "halted = false"
350
343
351
- each do |callback |
352
- method << callback . start ( key , object )
344
+ callbacks = yielding
345
+ applicable_callbacks_for ( key , object ) . reverse_each do |callback |
346
+ callbacks = callback . apply ( callbacks , key , object )
353
347
end
348
+ method << callbacks
349
+
350
+ method << "raise rescued_error if rescued_error" if config [ :rescuable ]
351
+ method << "halted ? false : (block_given? ? value : true)"
352
+ method . flatten . compact . join ( "\n " )
353
+ end
354
354
355
+ # Returns part of method that evaluates the callback block
356
+ def yielding
357
+ method = [ ]
355
358
if config [ :rescuable ]
356
359
method << "rescued_error = nil"
357
360
method << "begin"
@@ -364,14 +367,15 @@ def compile(key=nil, object=nil)
364
367
method << "rescued_error = e"
365
368
method << "end"
366
369
end
370
+ method . join ( "\n " )
371
+ end
367
372
368
- reverse_each do |callback |
369
- method << callback . end ( key , object )
373
+ # Selects callbacks that have valid <tt>:per_key</tt> condition
374
+ def applicable_callbacks_for ( key , object )
375
+ return self unless key
376
+ select do |callback |
377
+ callback . one_time_conditions_valid? ( object )
370
378
end
371
-
372
- method << "raise rescued_error if rescued_error" if config [ :rescuable ]
373
- method << "halted ? false : (block_given? ? value : true)"
374
- method . compact . join ( "\n " )
375
379
end
376
380
end
377
381
0 commit comments