Module: Interrobang

Defined in:
lib/interrobang.rb,
lib/interrobang/version.rb

Overview

Convert your ‘#predicate_methods?` to `#bang_methods!`

Constant Summary collapse

FalsePredicate =

Exception to raise when no block is provided for bangified falsey methods

Class.new(Exception)
DEFAULT_PATTERN =

Regexp that matches methods that end in question marks.

%r{\A[^?]+\?\z}
VERSION =
'1.0.0'

Class Method Summary collapse

Class Method Details

.bangify(klass, matching: DEFAULT_PATTERN, only: [], except: [], prefix: '', suffix: '', include_super: false) ⇒ Object

Converts the specified predicate methods in a class to bang methods.

Parameters:

  • klass

    The Class to target for bangification

  • block

    An optional block to run if a predicate method returns something falsey

Returns:

  • the Symbol Array of bangified method names.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/interrobang.rb', line 28

def bangify(klass, matching: DEFAULT_PATTERN, only: [], except: [], prefix: '', suffix: '', include_super: false)
  method_keys = klass.instance_methods(include_super)
  only = [only] unless only.is_a?(Array)
  except = [except] unless except.is_a?(Array)
  if only.empty?
    method_keys.map do |method_key|
      if method_key.to_s =~ matching && !except.include?(method_key)
        if block_given?
          bangify_method(klass, method_key, prefix: prefix, suffix: suffix, &Proc.new)
        else
          bangify_method(klass, method_key, prefix: prefix, suffix: suffix)
        end
      end
    end.compact
  else
    method_keys.map do |method_key|
      if only.include?(method_key)
        if block_given?
          bangify_method(klass, method_key, prefix: prefix, suffix: suffix, &Proc.new)
        else
          bangify_method(klass, method_key, prefix: prefix, suffix: suffix)
        end
      end
    end.compact
  end
end

.bangify_method(klass, predicate_method, prefix: '', suffix: '') ⇒ Object

Converts the specified predicate method to a bang method.

Parameters:

  • klass

    The Class to target for bangification

  • predicate_method

    The Symbol of the predicate method

  • block

    An optional block to run if a predicate method returns something falsey

Returns:

  • the Symbol name of the bang method created.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/interrobang.rb', line 68

def bangify_method(klass, predicate_method, prefix: '', suffix: '')
  predicate_method_string = predicate_method.to_s
  method_name_base =
    case predicate_method_string[-1]
    when '=', '!'
      return
    when '?'
      predicate_method.to_s[0..-2]
    else
      predicate_method.to_s
    end

  bang_method = :"#{prefix}#{method_name_base}#{suffix}!"

  klass.class_eval do
    if block_given?
      define_method(bang_method) do |*args, &block|
        if send(predicate_method, *args, &block)
          true
        else
          yield(predicate_method)
        end
      end
    else
      define_method(bang_method) do |*args, &block|
        if send(predicate_method, *args, &block)
          true
        else
          raise(Interrobang::FalsePredicate, "#{predicate_method} is false")
        end
      end
    end
  end
  bang_method
end