Module: Matchete

Defined in:
lib/matchete.rb,
lib/matchete/exceptions.rb

Defined Under Namespace

Modules: ClassMethods Classes: NotResolvedError

Constant Summary collapse

Any =
-> (x) { true }
None =
-> (x) { false }

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(klass) ⇒ Object



5
6
7
8
9
# File 'lib/matchete.rb', line 5

def self.included(klass)
  klass.extend ClassMethods
  klass.instance_variable_set "@methods", {}
  klass.instance_variable_set "@default_methods", {}
end

Instance Method Details

#call_overloaded(method_name, args: [], kwargs: {}) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/matchete.rb', line 79

def call_overloaded(method_name, args: [], kwargs: {})
  handler = find_handler(method_name, args, kwargs)

  if kwargs.empty?
    handler.bind(self).call *args
  else
    handler.bind(self).call *args, **kwargs
  end
  #insane workaround, because if you have
  #def z(f);end
  #and you call it like that
  #empty = {}
  #z(2, **empty)
  #it raises wrong number of arguments (2 for 1)
  #clean up later
end

#find_handler(method_name, args, kwargs) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/matchete.rb', line 96

def find_handler(method_name, args, kwargs)
  guards = self.class.instance_variable_get('@methods')[method_name].find do |guard_args, guard_kwargs, _|
    match_guards guard_args, guard_kwargs, args, kwargs
  end

  if guards.nil?
    default_method = self.class.instance_variable_get('@default_methods')[method_name]
    if default_method
      default_method
    else
      raise NotResolvedError.new("No matching #{method_name} method for args #{args}")
    end
  else
    guards.last
  end
end

#match_guard(guard, arg) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/matchete.rb', line 124

def match_guard(guard, arg)
  case guard
    when Module
      arg.is_a? guard
    when Symbol
      if guard.to_s[-1] == '?'
        send guard, arg
      else
        guard == arg
      end
    when Proc
      instance_exec arg, &guard
    when Regexp
      arg.is_a? String and guard.match arg
    when Array
      arg.is_a?(Array) and
      guard.zip(arg).all? { |child_guard, child| match_guard child_guard, child }
    else
      if guard.is_a?(String) && guard[0] == '#'
        arg.respond_to? guard[1..-1]
      else
        guard == arg
      end
  end
end

#match_guards(guard_args, guard_kwargs, args, kwargs) ⇒ Object



113
114
115
116
117
118
119
120
121
122
# File 'lib/matchete.rb', line 113

def match_guards(guard_args, guard_kwargs, args, kwargs)
  return false if guard_args.count != args.count ||
                  guard_kwargs.count != kwargs.count
  guard_args.zip(args).all? do |guard, arg|
    match_guard guard, arg
  end and
  guard_kwargs.all? do |label, guard|
    match_guard guard, kwargs[label]
  end
end