Dynamic is_ ? methods for boolean attributes of a model


08.24.10 Posted in Blog by admin

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.



5 Responses to “Dynamic is_ ? methods for boolean attributes of a model”

  1. bbc weather games says:

    That’s very thought-provoking point of view. I will return to your blog soon.

  2. great article, i just finished bookmarking it to regularly check it. i’d love to revisit on new articles. how do i set the RSS again? thanks!

  3. Pratik says:

    Rails’ attribute helper methods should help in this case.

    class User
    attribute_method_affix :prefix => ‘is_’, :suffix => ‘?’

    private

    def is_attribute?(attribute)
    send(attribute).present?
    end
    end

  4. Pratik says:

    Also, AR already defines ‘?’ attribute helpers. i.e available?, blocked? etc.

  5. Shadab Ahmed says:

    Thats a cool way to do it :)

    in my initializer i will have

    class ActiveRecord::Base

    private

    # your code

    end

Leave a Reply