Search This Blog

May 13, 2012

Rails and StringInquirer - A real world example

Use Case:
Assume a User model, having an association with UserProfile model. Also, presume that Admin, Artist, Exhibition Curator, Collector, etc are models that are inherited from UserProfile.

Now, if we'd like to know weather a given user is an admin or a collector or of any other profile type, we'll typically have to define methods like below in the User class:
We coule simplify the above methods using meta-programming technique to define methods at runtime, using "define_method" method.

However, there exists an easier and neater method. It is to employ the delegate and StringInquirer as below:
With any of the above implementations, we can test a given user instanse against a specific user profile type as below:
user.admin?
instead of
user.user_profile.type.titleize == "Admin"
As a matter of fact, starting Rails 2.3.x, if I'm right, you test for Rails environment with a code like the one below:
Rails.env.development?
instead of
Rails.env == "development" 
or
RAILS_ENV == "development"
Usage of RAILS_ENV and other such constants were depricated with Rails 2.3.x and completely removed beginning Rails 3.x

Lesson: For better code readability, wrap your string value with StringInquirer, especially in cases like the above examples.

It is good to know that StringInquirer is infact a sub-class of String, and that the above magic of boolean returning methods is achieved by way of method_missing implementation in the StringInquirer class.

Resources:

2 comments:

  1. Thanks, very nice tip! But in your case it wont work because "Admin".inquiry.admin == false. You might use "Admin".inquiry.Admin?, but that seems weird...

    What you actually want to do is:

    delegate :admin?, :artist?, :collector?, :estate?, :exhibition_curator?, :to => :user_profile_type

    def user_profile_type
    user.user_profile.type.downcase.inquiry
    end

    ReplyDelete
    Replies
    1. Good catch! Thanks and the changes are now incorporated :)

      Delete

Like it or hate it, feel free to share your feedback. Cheers!