Merged in more new callback stuff from rails 3
This commit is contained in:
parent
db7829e996
commit
f4f3946d86
2 changed files with 48 additions and 54 deletions
|
@ -142,12 +142,12 @@ module CouchRest
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_options!(options)
|
def normalize_options!(options)
|
||||||
options[:if] = Array(options[:if])
|
options[:if] = Array.wrap(options[:if])
|
||||||
options[:unless] = Array(options[:unless])
|
options[:unless] = Array.wrap(options[:unless])
|
||||||
|
|
||||||
options[:per_key] ||= {}
|
options[:per_key] ||= {}
|
||||||
options[:per_key][:if] = Array(options[:per_key][:if])
|
options[:per_key][:if] = Array.wrap(options[:per_key][:if])
|
||||||
options[:per_key][:unless] = Array(options[:per_key][:unless])
|
options[:per_key][:unless] = Array.wrap(options[:per_key][:unless])
|
||||||
end
|
end
|
||||||
|
|
||||||
def next_id
|
def next_id
|
||||||
|
@ -204,9 +204,10 @@ module CouchRest
|
||||||
filter = <<-RUBY_EVAL
|
filter = <<-RUBY_EVAL
|
||||||
unless halted
|
unless halted
|
||||||
result = #{@filter}
|
result = #{@filter}
|
||||||
halted ||= (#{terminator})
|
halted = (#{terminator})
|
||||||
end
|
end
|
||||||
RUBY_EVAL
|
RUBY_EVAL
|
||||||
|
|
||||||
[@compiled_options[0], filter, @compiled_options[1]].compact.join("\n")
|
[@compiled_options[0], filter, @compiled_options[1]].compact.join("\n")
|
||||||
else
|
else
|
||||||
# Compile around filters with conditions into proxy methods
|
# Compile around filters with conditions into proxy methods
|
||||||
|
@ -225,7 +226,7 @@ module CouchRest
|
||||||
# end
|
# end
|
||||||
|
|
||||||
name = "_conditional_callback_#{@kind}_#{next_id}"
|
name = "_conditional_callback_#{@kind}_#{next_id}"
|
||||||
txt = <<-RUBY_EVAL
|
txt, line = <<-RUBY_EVAL, __LINE__
|
||||||
def #{name}(halted)
|
def #{name}(halted)
|
||||||
#{@compiled_options[0] || "if true"} && !halted
|
#{@compiled_options[0] || "if true"} && !halted
|
||||||
#{@filter} do
|
#{@filter} do
|
||||||
|
@ -236,7 +237,7 @@ module CouchRest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
RUBY_EVAL
|
RUBY_EVAL
|
||||||
@klass.class_eval(txt)
|
@klass.class_eval(txt, __FILE__, line)
|
||||||
"#{name}(halted) do"
|
"#{name}(halted) do"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -271,11 +272,11 @@ module CouchRest
|
||||||
conditions = []
|
conditions = []
|
||||||
|
|
||||||
unless options[:if].empty?
|
unless options[:if].empty?
|
||||||
conditions << Array(_compile_filter(options[:if]))
|
conditions << Array.wrap(_compile_filter(options[:if]))
|
||||||
end
|
end
|
||||||
|
|
||||||
unless options[:unless].empty?
|
unless options[:unless].empty?
|
||||||
conditions << Array(_compile_filter(options[:unless])).map {|f| "!#{f}"}
|
conditions << Array.wrap(_compile_filter(options[:unless])).map {|f| "!#{f}"}
|
||||||
end
|
end
|
||||||
|
|
||||||
["if #{conditions.flatten.join(" && ")}", "end"]
|
["if #{conditions.flatten.join(" && ")}", "end"]
|
||||||
|
@ -306,33 +307,14 @@ module CouchRest
|
||||||
filter.map {|f| _compile_filter(f)}
|
filter.map {|f| _compile_filter(f)}
|
||||||
when Symbol
|
when Symbol
|
||||||
filter
|
filter
|
||||||
|
when String
|
||||||
|
"(#{filter})"
|
||||||
when Proc
|
when Proc
|
||||||
@klass.send(:define_method, method_name, &filter)
|
@klass.send(:define_method, method_name, &filter)
|
||||||
method_name << case filter.arity
|
return method_name if filter.arity == 0
|
||||||
when 1
|
|
||||||
"(self)"
|
method_name << (filter.arity == 1 ? "(self)" : " self, Proc.new ")
|
||||||
when 2
|
|
||||||
" self, Proc.new "
|
|
||||||
else
|
|
||||||
""
|
|
||||||
end
|
|
||||||
when Method
|
|
||||||
@klass.send(:define_method, "#{method_name}_method") { filter }
|
|
||||||
@klass.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
|
||||||
def #{method_name}(&blk)
|
|
||||||
#{method_name}_method.call(self, &blk)
|
|
||||||
end
|
|
||||||
RUBY_EVAL
|
|
||||||
method_name
|
|
||||||
when String
|
|
||||||
@klass.class_eval <<-RUBY_EVAL
|
|
||||||
def #{method_name}
|
|
||||||
#{filter}
|
|
||||||
end
|
|
||||||
RUBY_EVAL
|
|
||||||
method_name
|
|
||||||
else
|
else
|
||||||
kind = @kind
|
|
||||||
@klass.send(:define_method, "#{method_name}_object") { filter }
|
@klass.send(:define_method, "#{method_name}_object") { filter }
|
||||||
|
|
||||||
_normalize_legacy_filter(kind, filter)
|
_normalize_legacy_filter(kind, filter)
|
||||||
|
@ -349,7 +331,7 @@ module CouchRest
|
||||||
|
|
||||||
def _normalize_legacy_filter(kind, filter)
|
def _normalize_legacy_filter(kind, filter)
|
||||||
if !filter.respond_to?(kind) && filter.respond_to?(:filter)
|
if !filter.respond_to?(kind) && filter.respond_to?(:filter)
|
||||||
filter.metaclass.class_eval(
|
filter.class_eval(
|
||||||
"def #{kind}(context, &block) filter(context, &block) end",
|
"def #{kind}(context, &block) filter(context, &block) end",
|
||||||
__FILE__, __LINE__ - 1)
|
__FILE__, __LINE__ - 1)
|
||||||
elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around
|
elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around
|
||||||
|
@ -402,8 +384,9 @@ module CouchRest
|
||||||
# The _run_save_callbacks method can optionally take a key, which
|
# The _run_save_callbacks method can optionally take a key, which
|
||||||
# will be used to compile an optimized callback method for each
|
# will be used to compile an optimized callback method for each
|
||||||
# key. See #define_callbacks for more information.
|
# key. See #define_callbacks for more information.
|
||||||
def _define_runner(symbol, callbacks)
|
def _define_runner(symbol)
|
||||||
body = callbacks.compile(nil, :terminator => send("_#{symbol}_terminator"))
|
body = send("_#{symbol}_callback").
|
||||||
|
compile(nil, :terminator => send("_#{symbol}_terminator"))
|
||||||
|
|
||||||
body, line = <<-RUBY_EVAL, __LINE__
|
body, line = <<-RUBY_EVAL, __LINE__
|
||||||
def _run_#{symbol}_callbacks(key = nil, &blk)
|
def _run_#{symbol}_callbacks(key = nil, &blk)
|
||||||
|
@ -431,7 +414,7 @@ module CouchRest
|
||||||
def _create_keyed_callback(name, kind, obj, &blk)
|
def _create_keyed_callback(name, kind, obj, &blk)
|
||||||
@_keyed_callbacks ||= {}
|
@_keyed_callbacks ||= {}
|
||||||
@_keyed_callbacks[name] ||= begin
|
@_keyed_callbacks[name] ||= begin
|
||||||
str = send("_#{kind}_callbacks").
|
str = send("_#{kind}_callback").
|
||||||
compile(name, :object => obj, :terminator => send("_#{kind}_terminator"))
|
compile(name, :object => obj, :terminator => send("_#{kind}_terminator"))
|
||||||
|
|
||||||
class_eval "def #{name}() #{str} end", __FILE__, __LINE__
|
class_eval "def #{name}() #{str} end", __FILE__, __LINE__
|
||||||
|
@ -471,21 +454,21 @@ module CouchRest
|
||||||
# In that case, each action_name would get its own compiled callback
|
# In that case, each action_name would get its own compiled callback
|
||||||
# method that took into consideration the per_key conditions. This
|
# method that took into consideration the per_key conditions. This
|
||||||
# is a speed improvement for ActionPack.
|
# is a speed improvement for ActionPack.
|
||||||
def update_callbacks(name, filters = CallbackChain.new(name), block = nil)
|
def _update_callbacks(name, filters = CallbackChain.new(name), block = nil)
|
||||||
type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before
|
type = [:before, :after, :around].include?(filters.first) ? filters.shift : :before
|
||||||
options = filters.last.is_a?(Hash) ? filters.pop : {}
|
options = filters.last.is_a?(Hash) ? filters.pop : {}
|
||||||
filters.unshift(block) if block
|
filters.unshift(block) if block
|
||||||
|
|
||||||
responded = self.respond_to?(":_#{name}_callbacks")
|
|
||||||
|
|
||||||
callbacks = send("_#{name}_callbacks")
|
callbacks = send("_#{name}_callback")
|
||||||
yield callbacks, type, filters, options if block_given?
|
yield callbacks, type, filters, options if block_given?
|
||||||
|
|
||||||
_define_runner(name, callbacks)
|
_define_runner(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias_method :_reset_callbacks, :_update_callbacks
|
||||||
|
|
||||||
def set_callback(name, *filters, &block)
|
def set_callback(name, *filters, &block)
|
||||||
update_callbacks(name, filters, block) do |callbacks, type, filters, options|
|
_update_callbacks(name, filters, block) do |callbacks, type, filters, options|
|
||||||
filters.map! do |filter|
|
filters.map! do |filter|
|
||||||
# overrides parent class
|
# overrides parent class
|
||||||
callbacks.delete_if {|c| c.matches?(type, filter) }
|
callbacks.delete_if {|c| c.matches?(type, filter) }
|
||||||
|
@ -497,9 +480,9 @@ module CouchRest
|
||||||
end
|
end
|
||||||
|
|
||||||
def skip_callback(name, *filters, &block)
|
def skip_callback(name, *filters, &block)
|
||||||
update_callbacks(name, filters, block) do |callbacks, type, filters, options|
|
_update_callbacks(name, filters, block) do |callbacks, type, filters, options|
|
||||||
filters.each do |filter|
|
filters.each do |filter|
|
||||||
callbacks = send("_#{name}_callbacks=", callbacks.clone(self))
|
callbacks = send("_#{name}_callback=", callbacks.clone(self))
|
||||||
|
|
||||||
filter = callbacks.find {|c| c.matches?(type, filter) }
|
filter = callbacks.find {|c| c.matches?(type, filter) }
|
||||||
|
|
||||||
|
@ -517,17 +500,11 @@ module CouchRest
|
||||||
symbols.each do |symbol|
|
symbols.each do |symbol|
|
||||||
extlib_inheritable_accessor("_#{symbol}_terminator") { terminator }
|
extlib_inheritable_accessor("_#{symbol}_terminator") { terminator }
|
||||||
|
|
||||||
extlib_inheritable_accessor("_#{symbol}_callbacks") do
|
extlib_inheritable_accessor("_#{symbol}_callback") do
|
||||||
CallbackChain.new(symbol)
|
CallbackChain.new(symbol)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
|
_define_runner(symbol)
|
||||||
def self.reset_#{symbol}_callbacks
|
|
||||||
update_callbacks(:#{symbol})
|
|
||||||
end
|
|
||||||
|
|
||||||
self.set_callback(:#{symbol}, :before)
|
|
||||||
RUBY_EVAL
|
|
||||||
|
|
||||||
# Define more convenient callback methods
|
# Define more convenient callback methods
|
||||||
# set_callback(:save, :before) becomes before_save
|
# set_callback(:save, :before) becomes before_save
|
||||||
|
|
|
@ -168,6 +168,23 @@ class Array
|
||||||
# options(1, 2, :a => :b) # => {:a=>:b}
|
# options(1, 2, :a => :b) # => {:a=>:b}
|
||||||
def extract_options!
|
def extract_options!
|
||||||
last.is_a?(::Hash) ? pop : {}
|
last.is_a?(::Hash) ? pop : {}
|
||||||
end unless Array.respond_to?(:extract_options!)
|
end unless Array.new.respond_to?(:extract_options!)
|
||||||
|
|
||||||
|
# Wraps the object in an Array unless it's an Array. Converts the
|
||||||
|
# object to an Array using #to_ary if it implements that.
|
||||||
|
def self.wrap(object)
|
||||||
|
case object
|
||||||
|
when nil
|
||||||
|
[]
|
||||||
|
when self
|
||||||
|
object
|
||||||
|
else
|
||||||
|
if object.respond_to?(:to_ary)
|
||||||
|
object.to_ary
|
||||||
|
else
|
||||||
|
[object]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end unless Array.respond_to?(:wrap)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue