Parent

Class Index [+]

Quicksearch

ActiveSupport::Callbacks::Callback

Attributes

chain[RW]
filter[RW]
kind[RW]
options[RW]
per_key[RW]
klass[RW]
raw_filter[RW]

Public Class Methods

new(chain, filter, kind, options, klass) click to toggle source
     # File lib/active_support/callbacks.rb, line 106
106:       def initialize(chain, filter, kind, options, klass)
107:         @chain, @kind, @klass = chain, kind, klass
108:         normalize_options!(options)
109: 
110:         @per_key              = options.delete(:per_key)
111:         @raw_filter, @options = filter, options
112:         @filter               = _compile_filter(filter)
113:         @compiled_options     = _compile_options(options)
114:         @callback_id          = next_id
115: 
116:         _compile_per_key_options
117:       end

Public Instance Methods

_compile_per_key_options() click to toggle source
     # File lib/active_support/callbacks.rb, line 168
168:       def _compile_per_key_options
169:         key_options  = _compile_options(@per_key)
170: 
171:         @klass.class_eval           def _one_time_conditions_valid_#{@callback_id}?            true #{key_options[0]}          end, __FILE__, __LINE__ + 1
172:       end
_update_filter(filter_options, new_options) click to toggle source
     # File lib/active_support/callbacks.rb, line 153
153:       def _update_filter(filter_options, new_options)
154:         filter_options[:if].push(new_options[:unless]) if new_options.key?(:unless)
155:         filter_options[:unless].push(new_options[:if]) if new_options.key?(:if)
156:       end
clone(chain, klass) click to toggle source
     # File lib/active_support/callbacks.rb, line 119
119:       def clone(chain, klass)
120:         obj                  = super()
121:         obj.chain            = chain
122:         obj.klass            = klass
123:         obj.per_key          = @per_key.dup
124:         obj.options          = @options.dup
125:         obj.per_key[:if]     = @per_key[:if].dup
126:         obj.per_key[:unless] = @per_key[:unless].dup
127:         obj.options[:if]     = @options[:if].dup
128:         obj.options[:unless] = @options[:unless].dup
129:         obj
130:       end
end(key=nil, object=nil) click to toggle source

This will supply contents for around and after filters, but not before filters (for the backward pass).

     # File lib/active_support/callbacks.rb, line 234
234:       def end(key=nil, object=nil)
235:         return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")
236: 
237:         if @kind == :around || @kind == :after
238:           # if condition    # after_save :filter_name, :if => :condition
239:           #   filter_name
240:           # end
241:           if @kind == :after
242:             [@compiled_options[0], @filter, @compiled_options[1]].compact.join("\n")
243:           else
244:             "end"
245:           end
246:         end
247:       end
matches?(_kind, _filter) click to toggle source
     # File lib/active_support/callbacks.rb, line 149
149:       def matches?(_kind, _filter)
150:         @kind == _kind && @filter == _filter
151:       end
name() click to toggle source
     # File lib/active_support/callbacks.rb, line 141
141:       def name
142:         chain.name
143:       end
next_id() click to toggle source
     # File lib/active_support/callbacks.rb, line 145
145:       def next_id
146:         @@_callback_sequence += 1
147:       end
normalize_options!(options) click to toggle source
     # File lib/active_support/callbacks.rb, line 132
132:       def normalize_options!(options)
133:         options[:if] = Array.wrap(options[:if])
134:         options[:unless] = Array.wrap(options[:unless])
135: 
136:         options[:per_key] ||= {}
137:         options[:per_key][:if] = Array.wrap(options[:per_key][:if])
138:         options[:per_key][:unless] = Array.wrap(options[:per_key][:unless])
139:       end
recompile!(_options, _per_key) click to toggle source
     # File lib/active_support/callbacks.rb, line 158
158:       def recompile!(_options, _per_key)
159:         _update_filter(self.options, _options)
160:         _update_filter(self.per_key, _per_key)
161: 
162:         @callback_id      = next_id
163:         @filter           = _compile_filter(@raw_filter)
164:         @compiled_options = _compile_options(@options)
165:                             _compile_per_key_options
166:       end
start(key=nil, object=nil) click to toggle source

This will supply contents for before and around filters, and no contents for after filters (for the forward pass).

     # File lib/active_support/callbacks.rb, line 180
180:       def start(key=nil, object=nil)
181:         return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")
182: 
183:         # options[0] is the compiled form of supplied conditions
184:         # options[1] is the "end" for the conditional
185:         #
186:         if @kind == :before || @kind == :around
187:           if @kind == :before
188:             # if condition    # before_save :filter_name, :if => :condition
189:             #   filter_name
190:             # end
191:             filter =               unless halted                result = #{@filter}                halted = (#{chain.config[:terminator]})              end
192: 
193:             [@compiled_options[0], filter, @compiled_options[1]].compact.join("\n")
194:           else
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                def #{name}(halted)                #{@compiled_options[0] || "if true"} && !halted                  #{@filter} do                    yield self                  end                else                  yield self                end              end,  __FILE__, __LINE__ + 1
212:             "#{name}(halted) do"
213:           end
214:         end
215:       end

Private Instance Methods

_compile_filter(filter) click to toggle source

Filters support:

  Arrays::  Used in conditions. This is used to specify
            multiple conditions. Used internally to
            merge conditions from skip_* filters
  Symbols:: A method to call
  Strings:: Some content to evaluate
  Procs::   A proc to call with the object
  Objects:: An object with a before_foo method on it to call

All of these objects are compiled into methods and handled the same after this point:

  Arrays::  Merged together into a single filter
  Symbols:: Already methods
  Strings:: class_eval'ed into methods
  Procs::   define_method'ed into methods
  Objects::
    a method is created that calls the before_foo method
    on the object.
     # File lib/active_support/callbacks.rb, line 291
291:       def _compile_filter(filter)
292:         method_name = "_callback_#{@kind}_#{next_id}"
293:         case filter
294:         when Array
295:           filter.map {|f| _compile_filter(f)}
296:         when Symbol
297:           filter
298:         when String
299:           "(#{filter})"
300:         when Proc
301:           @klass.send(:define_method, method_name, &filter)
302:           return method_name if filter.arity <= 0
303: 
304:           method_name << (filter.arity == 1 ? "(self)" : " self, Proc.new ")
305:         else
306:           @klass.send(:define_method, "#{method_name}_object") { filter }
307: 
308:           _normalize_legacy_filter(kind, filter)
309:           scopes = Array.wrap(chain.config[:scope])
310:           method_to_call = scopes.map{ |s| s.is_a?(Symbol) ? send(s) : s }.join("_")
311: 
312:           @klass.class_eval             def #{method_name}(&blk)              #{method_name}_object.send(:#{method_to_call}, self, &blk)            end, __FILE__, __LINE__ + 1
313: 
314:           method_name
315:         end
316:       end
_compile_options(options) click to toggle source

Options support the same options as filters themselves (and support symbols, string, procs, and objects), so compile a conditional expression based on the options

     # File lib/active_support/callbacks.rb, line 254
254:       def _compile_options(options)
255:         return [] if options[:if].empty? && options[:unless].empty?
256: 
257:         conditions = []
258: 
259:         unless options[:if].empty?
260:           conditions << Array.wrap(_compile_filter(options[:if]))
261:         end
262: 
263:         unless options[:unless].empty?
264:           conditions << Array.wrap(_compile_filter(options[:unless])).map {|f| "!#{f}"}
265:         end
266: 
267:         ["if #{conditions.flatten.join(" && ")}", "end"]
268:       end
_normalize_legacy_filter(kind, filter) click to toggle source
     # File lib/active_support/callbacks.rb, line 322
322:       def _normalize_legacy_filter(kind, filter)
323:         if !filter.respond_to?(kind) && filter.respond_to?(:filter)
324:           filter.singleton_class.class_eval             def #{kind}(context, &block) filter(context, &block) end, __FILE__, __LINE__ + 1
325:         elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around
326:           def filter.around(context)
327:             should_continue = before(context)
328:             yield if should_continue
329:             after(context)
330:           end
331:         end
332:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.