A very common pattern observed in Rails models is a series of “is_{attribute}?” instance methods. Here, ‘attribute’ is usually a boolean column. I got tired of defining these similar methods. And adding to the misery, if the model structure changes to add another boolean field, you need to define another clone of the same method!
So, I ended up using this little trick. Ruby meta programming awesomeness helped, of course.
Consider a minimalistic Model called ‘User’ with an underlying ‘users’ table in the database.
User
Id, Login, Name, Email, Verified, Blocked, Available
I know the schema can be altered to take these 3 into a single field called “state” or something on those lines, but this is just a simple example. Here, the last 3 attributes are boolean. We need to define methods “is_verified?” , “is_blocked?” , “is_available?”.
Usually, we would define 3 instance methods or named_scopes to achieve the objective. Like so:
def is_verified?
self.verified
end
def is_blocked?
self.blocked
end
def is_available?
self.available
end
Annoying, right? Let’s try this:
def self.boolean_attributes
self.columns_hash.reject{|k,v| (v.type.to_s != 'boolean') }.keys
end
self.boolean_attributes.each do |boolean_attribute|
define_method "is_#{boolean_attribute}?" do
!!self.send(boolean_attribute)
end
end
There. If there are 12 boolean attributes, you have 12 methods defined dynamically! And if you change the schema, you still have “is_{new_attribute}?” in place automatically.