Proxying Definition

Patterns Are Not Scary: Method Missing Proxy
Proxying

A proxy, in its most general form, is a class functioning as an interface to something else.

An interface to something else. That sounds easy enough. You might be thinking that you have never used a proxy, but if you are reading this blog, you are wrong. Chances are you have used Rails, and if you have used Rails, chances are you have used has_many or some other ActiveRecord association, all of which are implemented using proxies under the hood.

Creating Your Own

Now that we have definition out of the way and have confirmed your use of proxies, let’s make one! Yay! The people rejoice! The basic idea of a proxy is a class that is an interface to something else. Lets call something else subject from now on. In order to get started, we’ll make a new proxy that has a subject.

class Proxy def initialize(subject) @subject = subject end end proxied_array = Proxy.new([1, 2, 3]) puts proxied_array.size # NoMethodError: undefined method ‘size’

FAIL! Our proxy has a subject (the array), but does not proxy anything yet. In order to proxy up the girl, lets throw in some method missing magic.

class Proxy def initialize(subject) @subject = subject end private def method_missing(method, *args, &block) @subject.send(method, *args, &block) end end proxied_array = Proxy.new([1, 2, 3]) puts proxied_array.size # 3

Method missing takes 3 arguments: the method called, the arguments passed to the method and a block if one is given. With just that tiny method missing addition, we can now do fun things like this:

proxied_array = Proxy.new([1, 2, 3]) puts proxied_array.size # 3 puts proxied_array[0] # 1 puts proxied_array[1] # 2 puts proxied_array[2] # 3 puts proxied_array.select { |a| a > 1 }.inspect # [2, 3] proxied_array < 4 puts proxied_array.size # 4 puts proxied_array[3] # 4

Just like that our proxied array behaves just like the original array. Well, almost like the original array.

puts proxied_array.class # Proxy

BlankSlate and BasicObject

Hmm, that is not quite what you would expect. We told the proxy to send everything to the subject, so it should output Array, not Proxy as the class, right? The problem is that any new class automatically has some methods included with it. In order for our Proxy class to be a true proxy, we need to remove those methods as well. In the Ruby 1.8 series, this is often done by defining a BlankSlate object which removes those methods and then have our Proxy inherit from BlankSlate.

class BlankSlate #:nodoc: instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval|object_id/ } end class Proxy < BlankSlate def initialize(subject) @subject = subject end private def method_missing(method, *args, &block) @subject.send(method, *args, &block) end end proxied_array = Proxy.new([1, 2, 3]) puts proxied_array.class # Array

Yay! Now we in fact get Array as one would expect. The great news is that Ruby 1.9 comes with a class like this already named BasicObject. The easy way to make this work with Ruby 1.8 and Ruby 1.9 is to just define BasicObject if it does not exist and then inherit from BasicObject, instead of dealing with BlankSlate.

Source: www.railstips.org

Related posts:

  1. Proxy Holder Definition
  2. By proxy Definition
  3. Proxy fight Definition
  4. Proxy bid Definition