Advanced Proxy Usage, Part I

August 8, 2007 Pivotal Labs

One of the more underutilized features of ActiveRecord is the Assocation Proxy. But they are also one of the most powerful weapons in the ActiveRecord armory, and Rails apps that take advantage of them are better organized and easier to maintain.

What is a Proxy?

When in an ActiveRecord you declare an Association:

class Hand < ActiveRecord::Base
  has_many :fingers

Instances of Hand now have a fingers method. Contrary to appearances, and contrary to the LIE told to you by hand.fingers.class, the fingers method does not return an Array of Fingers. Rather it returns a Proxy object, one that smells and tastes like an Array of fingers but actually has a rich creamy behavior all its own.

Scoped Access

The most basic use of Proxies is to “scope” the reading and writing of your ActiveRecords. For example, if you have a controller that allows CRUD on a User’s Assets, you can read and write to the collection of Assets as in the following examples:

@asset = current_user.assets.find(params[:id])
@asset = current_user.assets.create(params[:asset])
@asset =[:asset]) # equivalent to 'new'-ing an object rather than 'create'-ing it.

There are other ways of doing this, of course:

@asset = Asset.create({:user => current_user}.merge(params[:asset))

But the Proxy Code is much better: not only is the Proxy code terse, but it meaningfully expresses the relationship between objects in your domain: Users have many assets; this Asset is created in the context of this User.

Special Queries (or Custom Finders)

The various Association declarations–has_many, belongs_to, etc.–allow you to express much more than a simple Foreign Key relation. We can richly express in the Proxy Declarations concepts like ‘Assets that belong to a User’ and ‘Assets that don’t belong to a User’:


simply by declaring:

class User
  has_many :my_assets, :class_name => 'Asset', :conditions => 'user_id = #{id}'
  has_many :other_assets, :class_name => 'Asset', :conditions => 'user_id != #{id}'

Notice, in this last example, something peculiar: the use of single quotes (”) with variable substitution (#{…}). This is not a typo: the use of double-quotes, would perform variable interpolation when the has_many declaration is invoked. This is in the class-context–i.e., there is no instance yet. Rails always calls eval with a Binding of self when a call to one of the Proxy methods is performed, ensuring that this all comes together.

Let’s consider an alternative to this approach: declaring finders as instance methods.

class User
  def other_assets
    assets.find(:conditions => ["user_id != ?", id])

What’s wrong with this approach? Well, if you want to use this query in anything non-trivial–such as selecting the first ten of a User’s Assets–you have to write fancy code:

def other_assets(options)
  assets.find({:conditions => ...}.merge(options))

But good luck using this strategy to do pagination. You need to define my_assets and my_assets_count, too–have fun keeping your code DRY. With a proxy, we can just do something like:


In fact, all the richness of ActiveRecord class methods (and any other class methods of the Target type) are available to you here. Want to find all of a User’s assets that are in State pending?


Another example:

class Asset
  def self.find_portrait_assets
    find(:all, :conditions => 'height > width')



returns only those portrait assets owned by a user.

Proxy Options

Proxy declarations accept a number of interesting parameters. There are even “lifecycle” callbacks, like after_add, and before_destroy just like a normal ActiveRecord has before_create and so forth. You can hook into these by using an option.

class User
  has_many :assets, :after_add => [:send_email] do
  def send_email(r)

This after_add could be defined in the Asset class. But suppose Assets had a Polymorphic association. Both Users and Articles have many Assets. Our Business Rule is only to send email when a User adds an Asset, not an Article. We could write:

class Asset
  def after_create
     case owner
     when User
       # send email
     when Article

But this is clumsy! When we have logic to express about the relationship between things, the Proxy is the right place for it. Anywhere else is just smearing logic throughout your code.

Proxy Extensions

Consider the following example:

has_many :assets do
  def to_s

You can actually extend your Proxy Objects with an Anonymous module! When you have logic that applies to a Collection of ActiveRecords, your has_many Proxy is probably the proper place for it. For example:

class Table
  has_many :cells do
    def to_matrix
      # convert from list to matrix form.

Another example of this technique is the following. Suppose an Asset as many Versions, such as small, medium, etc. We’d prefer a shorter way of finding the proper version of an Asset than saying asset.versions.find_by_name('thumbnail'), we’d like to just say asset.versions[:thumbnail]. Just define the brackets ([]) operator on the Proxy:

class Asset
  has_many :versions, :class_name => 'Asset', :foreign_key => :parent_id do
    def [](version_name)

Suppose we want to go one step further. If a particular version doesn’t exist, it shall be created on-the-fly:

def [](version_name)
  if version = find_by_name(version_name)
    # create a new version here.

Advanced Extensions

In some cases, we want to write generic Extensions–these should work regardless of the particular classes involved. In the context of a Proxy there are three methods you should be aware of: proxy_owner, proxy_target, and proxy_reflection.

Suppose we want to implement something like the build method, but one that doesn’t have the side effect of adding it to the owner in memory:

has_many :foo do
  def new(options = {}){proxy_reflection.primary_key_name =>}.merge(options))

Extensions are so useful–it just requires a little imagination–that I’m going to give one more example, this one apropos of Access Control:

class User
  has_many :draft_articles do
    def readable_by?(user)
      user == proxy_owner

Some Miscellany

  1. The has_one and belongs_to Proxies behave a bit oddly: here, cyclops.build_eye is used rather than the more obvious

  2. In general, has_one and belongs_to will shadow methods on the Target. Don’t name any database columns target or owner, for instance. This is one of the biggest complaints against the current implementation of Proxies!

  3. Both build and create will work even if the Proxy Owner is new. For example, u =;; In this example, both objects will be saved with the Foreign Key set correctly.

  4. Both build and create can take an array of attributes hashes. For example:[{...}, {...}]). This will build two assets at once. (This is quite nice where in a Controller you have a form that allows the upload of multiple Assets at once. The Controller code looks identical (in simple cases) regardless of whether the form allows a single or multiple upload!)

That’s the basic idea. In part II of this Article (to be released in the coming weeks), I will discuss ‘static’ Proxy methods and I will release version 0.1 of a new plugin that builds upon a lot of exciting work in this area. In the meantime, check this out.

About the Author


Taking a break from Rspec
Taking a break from Rspec

On my next new project, I think I'm going back to Test::Unit. I've lost patience with Rspec, and it seems l...

doing it again and again
doing it again and again

Here's an RSpec trick I discovered yesterday. Sometimes when you're writing a test you want to loop over so...

SpringOne 2021

Register Now