Module: Gamera::GeneralProxy

Defined in:
lib/gamera/general_proxy.rb

Overview

This implements a specific sub-pattern of the proxy pattern. Rather than knowing about a specific class's methods, it will add a singleton method to a given object for each method defined by that method's class or the method's class and up through a specified class in the ancestor chain.

Important Note: This module must be prepended rather than included for self to refer to the class containing the module. If the proxying isn't happening, this is likely the problem.

Usage example: if you are testing a class Foo with Capybara and you'd like to take a screenshot everytime a method in that class is called

class Foo
  prepend Gamera::GeneralProxy

  def my_method
    # do something interesting in a browser
  end

  def my_other_method
    # do something else interesting in a browser
  end
end

In the spec file

describe Foo do
  let(:foo) { Foo.new }
  it "does something"
  foo.start_proxying(->(*args)
    {Capybara::Screenshot.screenshot_and_save_page
      super(*args)})
  foo.my_method # => screenshot taken & method called
  foo.my_other_method # => screenshot taken & method called
  foo.stop_proxying
  foo.my_method # => *crickets* (aka method called)
  foo.my_other_method # => *crickets*
  ...

Instance Method Summary collapse

Instance Method Details

#start_proxying(a_lambda = ->(*args) { super(*args) }, top_class = self.class) ⇒ Object


68
69
70
71
72
73
74
75
76
77
# File 'lib/gamera/general_proxy.rb', line 68

def start_proxying(a_lambda = ->(*args) { super(*args) }, top_class = self.class)
  @top_class = top_class
  ancestors = self.class.ancestors
  proxy_target_classes = ancestors[1..ancestors.index(top_class)]
  proxy_target_classes.each do |klass|
    klass.instance_methods(false).each do |method|
      define_singleton_method(method, a_lambda)
    end
  end
end

#stop_proxyingObject


79
80
81
# File 'lib/gamera/general_proxy.rb', line 79

def stop_proxying
  start_proxying(-> (*args) { super(*args) }, @top_class)
end