class Functo

Constants

MAX_ATTRIBUTES
PASS
VERSION

Public Class Methods

call(*args) click to toggle source
# File lib/functo.rb, line 24
def call(*args)
  new(*parse_args(args))
end
new(attributes, function, filters) click to toggle source
# File lib/functo.rb, line 53
def initialize(attributes, function, filters)
  @attributes = attributes
  @function = function
  @filters = filters

  @attributes_module = Module.new
  @function_module = Module.new

  define_initialize
  define_readers
  define_call
end
pass() click to toggle source
# File lib/functo.rb, line 20
def pass
  PASS
end
wrap(function = nil, &block) click to toggle source
# File lib/functo.rb, line 11
def wrap(function = nil, &block)
  function ||= block if block_given?

  Class.new.tap do |klass|
    klass.define_singleton_method(:call, &function)
    klass.extend(Functo::Compose)
  end
end

Private Class Methods

parse_args(args) click to toggle source
# File lib/functo.rb, line 30
def parse_args(args)
  function, *inputs = *args

  if inputs.first.is_a?(Hash)
    inputs = inputs.first

    attributes = inputs.keys
    filters = inputs.values
  else
    attributes = inputs
    filters = [pass] * inputs.length
  end

  if attributes.length > MAX_ATTRIBUTES
    raise ArgumentError.new("given #{attributes.length} attributes when only #{MAX_ATTRIBUTES} are allowed")
  end

  [attributes, function, filters]
end

Private Instance Methods

apply_filters(args) click to toggle source
# File lib/functo.rb, line 116
def apply_filters(args)
  args.zip(@filters).map do |arg, filter|
    if filter.equal?(Functo.pass)
      arg
    elsif filter.respond_to?(:to_proc)
      filter.to_proc.call(arg)
    elsif filter.respond_to?(:call)
      filter.call(arg)
    elsif filter.respond_to?(:[])
      filter[arg]
    else
      raise ArgumentError.new("filters must respond to `to_proc`, `call`, or `[]`")
    end
  end
end
define_call() click to toggle source
# File lib/functo.rb, line 106
def define_call
  function = @function

  @function_module.class_eval do
    define_method :call do |*args, &block|
      new(*args).public_send(function, &block)
    end
  end
end
define_initialize() click to toggle source
# File lib/functo.rb, line 73
def define_initialize
  ivars = @attributes.map { |name| "@#{name}" }
  size = @attributes.size
  filter = method(:apply_filters).to_proc

  @attributes_module.class_eval do
    define_method :initialize do |*args|
      args_size = args.size

      if args_size != size
        message = "wrong number of arguments (#{args_size} for #{size})"

        raise ArgumentError.new(message)
      end

      ivars.zip(filter.call(args)) do |ivar, arg|
        instance_variable_set(ivar, arg)
      end
    end

    private :initialize
  end
end
define_readers() click to toggle source
# File lib/functo.rb, line 97
def define_readers
  attributes = @attributes

  @attributes_module.class_eval do
    attr_reader(*attributes)
    protected(*attributes)
  end
end
included(host) click to toggle source
# File lib/functo.rb, line 66
def included(host)
  host.include(@attributes_module)
  host.extend(@function_module)

  host.extend(Functo::Compose)
end