class CouchRest::Mixins::Callbacks::Callback

Attributes

filter[RW]
kind[RW]
klass[RW]
name[RW]
options[RW]
per_key[RW]

Public Instance Methods

_compile_per_key_options() click to toggle source
# File lib/couchrest/mixins/callbacks.rb, line 176
        def _compile_per_key_options
          key_options  = _compile_options(@per_key)

          @klass.class_eval "            def _one_time_conditions_valid_#{@callback_id}?
              true #{key_options[0]}
            end
", __FILE__, __LINE__ + 1
        end
_update_filter(filter_options, new_options) click to toggle source
# File lib/couchrest/mixins/callbacks.rb, line 161
def _update_filter(filter_options, new_options)
  filter_options[:if].push(new_options[:unless]) if new_options.key?(:unless)
  filter_options[:unless].push(new_options[:if]) if new_options.key?(:if)
end
clone(klass) click to toggle source
# File lib/couchrest/mixins/callbacks.rb, line 131
def clone(klass)
  obj                  = super()
  obj.klass            = klass
  obj.per_key          = @per_key.dup
  obj.options          = @options.dup
  obj.per_key[:if]     = @per_key[:if].dup
  obj.per_key[:unless] = @per_key[:unless].dup
  obj.options[:if]     = @options[:if].dup
  obj.options[:unless] = @options[:unless].dup
  obj
end
end(key = nil, options = {}) click to toggle source

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

# File lib/couchrest/mixins/callbacks.rb, line 247
def end(key = nil, options = {})
  object = (options || {})[:object]

  return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")

  if @kind == :around || @kind == :after
    # if condition    # after_save :filter_name, :if => :condition
    #   filter_name
    # end
    if @kind == :after
      [@compiled_options[0], @filter, @compiled_options[1]].compact.join("\n")
    else
      "end"
    end
  end
end
matches?(_kind, _filter) click to toggle source
# File lib/couchrest/mixins/callbacks.rb, line 156
def matches?(_kind, _filter)
  @kind   == _kind &&
  @filter == _filter
end
next_id() click to toggle source
# File lib/couchrest/mixins/callbacks.rb, line 152
def next_id
  @@_callback_sequence += 1
end
normalize_options!(options) click to toggle source
# File lib/couchrest/mixins/callbacks.rb, line 143
def normalize_options!(options)
  options[:if] = Array.wrap(options[:if])
  options[:unless] = Array.wrap(options[:unless])

  options[:per_key] ||= {}
  options[:per_key][:if] = Array.wrap(options[:per_key][:if])
  options[:per_key][:unless] = Array.wrap(options[:per_key][:unless])
end
recompile!(_options, _per_key) click to toggle source
# File lib/couchrest/mixins/callbacks.rb, line 166
def recompile!(_options, _per_key)
  _update_filter(self.options, _options)
  _update_filter(self.per_key, _per_key)

  @callback_id      = next_id
  @filter           = _compile_filter(@raw_filter)
  @compiled_options = _compile_options(@options)
                      _compile_per_key_options
end
start(key = nil, options = {}) 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/couchrest/mixins/callbacks.rb, line 188
        def start(key = nil, options = {})
          object, terminator = (options || {}).values_at(:object, :terminator)

          return if key && !object.send("_one_time_conditions_valid_#{@callback_id}?")

          terminator ||= false

          # options[0] is the compiled form of supplied conditions
          # options[1] is the "end" for the conditional

          if @kind == :before || @kind == :around
            if @kind == :before
              # if condition    # before_save :filter_name, :if => :condition
              #   filter_name
              # end
              filter = <<-RUBY_EVAL
                unless halted
                  result = #{@filter}
                  halted = (#{terminator})
                end
              RUBY_EVAL
              
              [@compiled_options[0], filter, @compiled_options[1]].compact.join("\n")
            else
              # Compile around filters with conditions into proxy methods
              # that contain the conditions.
              #
              # For `around_save :filter_name, :if => :condition':
              #
              # def _conditional_callback_save_17
              #   if condition
              #     filter_name do
              #       yield self
              #     end
              #   else
              #     yield self
              #   end
              # end

              name = "_conditional_callback_#{@kind}_#{next_id}"
              txt, line = "                def #{name}(halted)
                  #{@compiled_options[0] || "if true"} && !halted
                    #{@filter} do
                      yield self
                    end
                  else
                    yield self
                  end
                end
", __LINE__ + 1
              @klass.class_eval(txt, __FILE__, line)
              "#{name}(halted) do"
            end
          end
        end

Public Class Methods

new(filter, kind, options, klass) click to toggle source
# File lib/couchrest/mixins/callbacks.rb, line 117
def initialize(filter, kind, options, klass)
  @kind, @klass = kind, klass

  normalize_options!(options)

  @per_key              = options.delete(:per_key)
  @raw_filter, @options = filter, options
  @filter               = _compile_filter(filter)
  @compiled_options     = _compile_options(options)
  @callback_id          = next_id

  _compile_per_key_options
end