# :main: README module MethodChain private # arg = Message | Code # Message = Symbol | [Symbol, *arguments] # Code.to_proc = Proc def send_as_function arg case arg when Symbol then __send__ arg when Array then __send__(*arg) else yield_or_eval(&arg) end end # send_as_function with multiple args, returns self def send_as_functions *args args.each {|arg| send_as_function arg} self end # yield or instance_eval based on the block arity def yield_or_eval &block case block.arity # ruby bug for -1 when 0, -1 then instance_eval(&block) when 1 then yield(self) else raise ArgumentError, "too many arguments required by block" end end public # send messages, evaluate blocks, but always return self def tap *messages, &block send_as_functions *messages unless messages.empty? yield_or_eval(&block) if block_given? self end # method chaining with a guard. # If no guard block is given then guard against nil and false def chain *messages, &guard return self if messages.empty? or not( (block_given? ? (yield_or_eval(&guard)) : self)) (send_as_function (messages.shift)).chain(*messages, &guard) end # return self if self or a guard evaluates to false, # otherwise return the evaluation of the block def then *guards, &block if guards.empty? return self if not self else guards.each do |cond| return self if not send_as_function(cond) end end block_given? ? yield_or_eval(&block) : self end # return self if self or a guard evaluates to true # otherwise return the evaluation of the block def else *guards, &block if guards.empty? return self if self else guards.each do |cond| return self if send_as_function(cond) end end block_given? ? yield_or_eval(&block) : self end # with no guards, is equivalent to self && yield_or_eval(&block) && self # same as: self.then(*guards, &block) && self def and *guards, &block if guards.empty? return self if not self else guards.each do |cond| return self if not send_as_function(cond) end end block_given? ? (yield_or_eval(&block) && self) : self end # with no guards, is equivalent to self || (yield_or_eval(&block) && self) # same as: self.else(*guards, &block) && self def or *guards, &block if guards.empty? return self if self else guards.each do |cond| return self if send_as_function(cond) end end block_given? ? yield_or_eval(&block) : self end end