Module: RetryUnsafeMethod::RetryUnsafeMethod::ClassMethods

Defined in:
lib/retry_unsafe_method/retry_unsafe_method.rb

Instance Method Summary collapse

Instance Method Details

#retry_unsafe_method(method_name, retry_count, *exceptions, &block) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
54
55
56
57
58
59
60
# File 'lib/retry_unsafe_method/retry_unsafe_method.rb', line 10

def retry_unsafe_method(method_name, retry_count, *exceptions, &block)

  unless method_defined?(method_name) || private_method_defined?(method_name)
    raise StandardError.new("method #{method_name} is not defined")
  end

  if block_given?
    raise StandardError.new('you must not pass exceptions and block simultaneously') if exceptions.size > 0
    check_proc = block
  else
    raise StandardError.new('you must pass exceptions or block') if exceptions.size == 0
    check_proc = Proc.new { |e| exceptions.map(&:to_s).include?(e.class.to_s) }
  end

  safe_method_name = :"#{method_name}_safe_with_retry"
  unsafe_method_name = :"#{method_name}_unsafe_without_retry"

  define_method(safe_method_name) do |*args, &block|
    begin
      __send__(unsafe_method_name, *args, &block)
    rescue StandardError => e
      ivar = :"@current_retry_#{method_name}"
      if check_proc.call(e)
        instance_variable_set(ivar, 0) unless instance_variable_defined?(ivar)

        if instance_variable_get(ivar) < retry_count
          instance_variable_set(ivar, instance_variable_get(ivar) + 1)
          retry
        else
          remove_instance_variable(ivar)
          raise e
        end

      else
        remove_instance_variable(ivar) if instance_variable_defined?(ivar)
        raise e
      end
    end
  end # define_method

  if private_method_defined?(method_name)
    private safe_method_name
  elsif protected_method_defined?(method_name)
    protected safe_method_name
  else
    public safe_method_name
  end

  alias_method unsafe_method_name, method_name
  alias_method method_name, safe_method_name
end