lib/chanko/invoker.rb
require "chanko/invoker/options"
require "chanko/invoker/function_finder"
module Chanko
module Invoker
def invoke(*args, &block)
options = Options.new(*args)
__with_default_stack(block) do
__with_unit_locals_stack(options.locals) do
if function = FunctionFinder.find(self, options)
function.invoke(self, options.invoke_options)
else
run_default
end
end
end
end
def units
@units ||= []
end
def view?
is_a?(ActionView::Base)
end
def run_default
__invoke_default_block if __has_default_block?
end
private
def method_missing(method_name, *args, &block)
if shared_method = __find_shared_method(method_name)
instance_exec(*args, &shared_method)
elsif args.empty? && __find_unit_local(method_name)
__fetch_unit_local(method_name)
else
super
end
end
def __find_unit_local(method_name)
__current_unit_locals.has_key?(method_name)
end
def __fetch_unit_local(method_name)
__current_unit_locals[method_name]
end
def __current_unit_locals
__unit_locals_stack.last || {}
end
def __unit_locals_stack
@__unit_locals_stack ||= []
end
def __find_shared_method(method_name)
__current_shared_methods[method_name]
end
def __current_shared_methods
__current_unit.try(:shared_methods) || {}
end
def __current_unit
units.last
end
def __defaults_stack
@__defaults_stack ||= []
end
def __default_block
__defaults_stack.last
end
def __has_default_block?
!!__default_block
end
def __invoke_default_block
current_default_block = __default_block
begin
__without_default_stack do
__without_locals_stack do
if view?
capture(¤t_default_block)
else
instance_exec(¤t_default_block)
end
end
end
end
end
def __with_default_stack(default)
__defaults_stack << default
yield
ensure
__defaults_stack.pop
end
def __with_unit_locals_stack(locals)
__unit_locals_stack << locals
yield
ensure
__unit_locals_stack.pop
end
def __without_default_stack
default = __defaults_stack.pop
yield
ensure
__defaults_stack << default
end
def __without_locals_stack
locals = __unit_locals_stack.pop
yield
ensure
__unit_locals_stack << locals
end
end
end