Module: Rubee::Hookable::ClassMethods

Defined in:
lib/rubee/extensions/hookable.rb

Instance Method Summary collapse

Instance Method Details

#after(*methods, handler, **options) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/rubee/extensions/hookable.rb', line 25

def after(*methods, handler, **options)
  methods.each do |method|
    hook = Module.new do
      define_method(method) do |*args, &block|
        result = super(*args, &block)

        if conditions_met?(options[:if], options[:unless])
          handler.respond_to?(:call) ? safe_call(handler, [self, args]) : send(handler)
        end

        result
      end
    end

    options[:class_methods] ? singleton_class.prepend(hook) : prepend(hook)
  end
end

#around(*methods, handler, **options) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rubee/extensions/hookable.rb', line 43

def around(*methods, handler, **options)
  methods.each do |method|
    hook = Module.new do
      define_method(method) do |*args, &block|
        if conditions_met?(options[:if], options[:unless])
          if handler.respond_to?(:call)
            result = nil
            handler_result = safe_call(handler, [self, args]) do
              result = super(*args, &block)
            end

            result || handler_result
          else
            send(handler) do
              super(*args, &block)
            end
          end
        else
          super(*args, &block)
        end
      end
    end

    options[:class_methods] ? singleton_class.prepend(hook) : prepend(hook)
  end
end

#before(*methods, handler, **options) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/rubee/extensions/hookable.rb', line 9

def before(*methods, handler, **options)
  methods.each do |method|
    hook = Module.new do
      define_method(method) do |*args, &block|
        if conditions_met?(options[:if], options[:unless])
          handler.respond_to?(:call) ? safe_call(handler, [self, args]) : send(handler)
        end

        super(*args, &block)
      end
    end

    options[:class_methods] ? singleton_class.prepend(hook) : prepend(hook)
  end
end

#conditions_met?(if_condition = nil, unless_condition = nil, instance = nil) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/rubee/extensions/hookable.rb', line 70

def conditions_met?(if_condition = nil, unless_condition = nil, instance = nil)
  return true if if_condition.nil? && unless_condition.nil?
  if_condition_result =
    if if_condition.nil?
      true
    elsif if_condition.respond_to?(:call)
      safe_call(if_condition, [instance])
    elsif instance.respond_to?(if_condition)
      instance.send(if_condition)
    end
  unless_condition_result =
    if unless_condition.nil?
      false
    elsif unless_condition.respond_to?(:call)
      safe_call(unless_condition, [instance])
    elsif instance.respond_to?(unless_condition)
      instance.send(unless_condition)
    end

  if_condition_result && !unless_condition_result
end

#safe_call(handler, call_args = [], &block) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/rubee/extensions/hookable.rb', line 92

def safe_call(handler, call_args = [], &block)
  if handler.is_a?(Proc)
    wrapped = safe_lambda(handler, &block)

    # Forward block to the handler lambda if present
    if block
      wrapped.call(*call_args, &block)
    else
      wrapped.call(*call_args)
    end
  else
    handler.call
    block&.call
  end
end

#safe_lambda(strict_lambda, &block) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/rubee/extensions/hookable.rb', line 108

def safe_lambda(strict_lambda, &block)
  return strict_lambda unless strict_lambda.is_a?(Proc)
  return strict_lambda unless strict_lambda.lambda?
  return strict_lambda unless strict_lambda.arity >= 0

  proc do |*call_args|
    lambda_arity = strict_lambda.arity

    # Take only what lambda can handle, pad missing ones with nil
    args_for_lambda = call_args.first(lambda_arity)
    if args_for_lambda.length < lambda_arity
      args_for_lambda += Array.new(lambda_arity - args_for_lambda.length, nil)
    end

    strict_lambda.call(*args_for_lambda, &block)
  end
end