module ProxyMethod::ClassMethods
Constants
- DEFAULT_PREFIX
- DEFAULT_PROXY_MESSAGE
Public Instance Methods
Return a proxied version of this class.
If the class has previously been “unproxied”, this returns a copy where all proxies are re-enabled.
# File lib/proxy_method.rb, line 243 def proxied self.dup.send(:reproxy!) end
Proxy one or more inherited class methods, so that they are not used directly. Given this base class:
class Animal def self.create 'created' end def destroy 'destroyed' end end
The simplest implementation is to pass just a single method name:
class Dog < Animal proxy_class_method :create end Dog.create # => RuntimeError: Disabled by proxy_method Dog.destroy # => 'destroyed'
Or multiple method names:
class Dog < Animal proxy_class_method :create, :destroy end Dog.create # => RuntimeError: Disabled by proxy_method Dog.destroy # => RuntimeError: Disabled by proxy_method
With a custom error message:
class Dog < Animal proxy_class_method :create, raise: 'Disabled!' end Dog.create # => RuntimeError: Disabled!
You can still access the unproxied version by prefixing 'unproxied_' to the method name:
Dog.unproxied_create # => 'created'
And you can change the prefix for unproxied versions:
class Dog < Animal proxy_class_method :create, prefix: 'original_' end Dog.original_create # => 'created'
Finally, you can actually proxy the method, by providing an alternative block of code to run:
class Dog < Animal proxy_class_method(:create) do |object, method_name, *args, &block| "indirectly #{object.send(method_name)}" end end Dog.create # => 'indirectly created'
# File lib/proxy_method.rb, line 80 def proxy_class_method(*original_method_names, &proxy_block) options = if original_method_names.last.is_a?(Hash) original_method_names.pop else {} end original_method_names = Array(original_method_names).flatten error_message = options[:raise] || DEFAULT_PROXY_MESSAGE prefix = options[:prefix] || DEFAULT_PREFIX original_method_names.each do |original_method_name| proxied_class_methods.merge!(original_method_name => prefix) new_method_name = :"#{prefix}#{original_method_name}" self.singleton_class.send(:alias_method, new_method_name, original_method_name) define_singleton_method(original_method_name) do |*args, &block| if proxy_class_methods_enabled? if proxy_block proxy_block.call(self.unproxied, original_method_name, *args, &block) else raise error_message end else send(new_method_name, *args, &block) end end end end
Proxy one or more inherited instance methods, so that they are not used directly. Given this base class:
class Animal def save 'saved' end def update 'updated' end end
The simplest implementation is to pass just a single method name:
class Dog < Animal proxy_instance_method :save end Dog.new.save # => RuntimeError: Disabled by proxy_method Dog.new.upate # => 'updated'
Or use the shorthand form:
class Dog < Animal proxy_method :save end
Or multiple method names:
class Dog < Animal proxy_method :save, :update end Dog.new.save # => RuntimeError: Disabled by proxy_method Dog.new.update # => RuntimeError: Disabled by proxy_method
With a custom error message:
class Dog < Animal proxy_method :save, raise: 'Disabled!' end Dog.new.save # => RuntimeError: Disabled!
You can still access the unproxied version by prefixing 'unproxied_' to the method name:
Dog.new.unproxied_save # => 'saved'
And you can change the prefix for unproxied versions:
class Dog < Animal proxy_method :save, prefix: 'original_' end Dog.new.original_save # => 'saved'
Finally, you can actually proxy the method, by providing an alternative block of code to run:
class Dog < Animal proxy_method(:save) do |object, method_name, *args, &block| "indirectly #{object.send(method_name)}" end end Dog.new.save # => 'indirectly saved'
# File lib/proxy_method.rb, line 192 def proxy_instance_method(*original_method_names, &proxy_block) options = if original_method_names.last.is_a?(Hash) original_method_names.pop else {} end original_method_names = Array(original_method_names).flatten error_message = options[:raise] || DEFAULT_PROXY_MESSAGE prefix = options[:prefix] || DEFAULT_PREFIX original_method_names.each do |original_method_name| proxied_instance_methods.merge!(original_method_name => prefix) new_method_name = :"#{prefix}#{original_method_name}" alias_method new_method_name, original_method_name define_method(original_method_name) do |*args, &block| if proxy_instance_methods_enabled? if proxy_block proxy_block.call(self.unproxied, original_method_name, *args, &block) else raise error_message end else send(new_method_name, *args, &block) end end end end
Return an unproxied version of this class.
This returns a copy of the class where all proxies are disabled. This is sometimes necessary when a proxied method is being called by a different method outside your control.
# File lib/proxy_method.rb, line 233 def unproxied self.dup.send(:unproxy!) end
Private Instance Methods
# File lib/proxy_method.rb, line 258 def proxied_class_methods @_proxied_class_methods ||= {} end
# File lib/proxy_method.rb, line 254 def proxied_instance_methods @_proxied_instance_methods ||= {} end
# File lib/proxy_method.rb, line 249 def proxy_class_methods_enabled? return @_proxy_class_methods_enabled if defined?(@_proxy_class_methods_enabled) @_proxy_class_methods_enabled = true end
# File lib/proxy_method.rb, line 267 def reproxy! @_proxy_class_methods_enabled = true self end
# File lib/proxy_method.rb, line 262 def unproxy! @_proxy_class_methods_enabled = false self end