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 ||= {}
end

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)
begin
super
rescue
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?
end
end

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!

About these ads

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: