Using method_missing to cleanup your models

I’ve inherited an Entity-Attribute-Value (EAV) database setup at work.  I’ve never really seen this used at the scale that it was used.  EAV’s are great for rapidly changing database fields, until now I’ve seen them mostly for select box’s and configurations.

In my instance, I have a main table for items and the rest of the attributes can be looked up.  EAV’s in Rails actually is easier than it was implemented in PHP.  However, the ever changing attributes would be better setup using meta-programing.

In my model, I define an attributes method, like so:

def attributes
@attribute ||= {}

This makes an attribute instance available for my method_missing call.  In particular, I’ll need to make a call to the database, so this caches the result for me.

Now for the real magic.  Typically, the item record has an id, itemcode, product_type, and title.  So I can call “item.title” and get the item’s title.  Other attributes like the “subtitle”, “price”, and “image” are not.  Using method_missing I can get at them as if they were part of the item model.

def method_missing(method)
return attributes[method.to_sym] if attributes[method.to_sym]
attributes[method.to_sym] = Attribute::get(itemcode, method.to_s) unless method.nil? || method.blank?

The begin… rescue blocks test method missing and rescue block is the code needed access the attributes.  Calling super, keeps method_missing functionality in place.  If that fails, it checks the attributes hash, then calls the Attribute::get method.

With over 330 possible attributes (and counting), I’ll be able to access them all like they are part of the item!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: