Refactoring With Helpers

Bit of a follow up to my last post, with mucho thanks to the guys at the FV.rb who helped out, @pennyminder and @dkubb.

I originally figured I needed to do some dynamic methods like you can do in Perl to auto-create methods, but it turns out the better way to do it nicely (or more nicely) was refactor my previous code is two areas.

First is to move the view logic (ie: each user having a URL attached to them) out of the controller and into a helper and to reverse it, so instead of having  “<rolename>?” method for each user type (ie: user.referee? user.assignor?) having a nice little method that just resolves the role path for the user.

  # application_helper.rb
  def user_role_path(user)
    role_path = {
      'clubadmin' =&gt; '/some/admin/path',
      'referee'   =&gt; bids_path(user),
      'assignor'  =&gt; assignor_path(user),
    }
    role_path[user.role.name.downcase]
  end

I don’t like having to have the hash in here, but since that is view specific, it seems to work nicely. Anyway, this gives me the ability to call this view specific code in my view and by using the following I can output the correct path based on the user.

# _header.html.erb
&lt;%= link_to "My Page", user_role_path(session[:user]) %&gt;

Also whereas the application helpers get access to all the “view” stuff, ie: it knows how to resolve something like bids_path(user), the controllers don’t have the RESTful functions, but can if you pull in the helper code. IE:

# users_controller.rb
  # pull in the helper functions from application_helper.rb
  include ApplicationHelper
  [...]
  def login
    # [...] authenticate
    # and now redirect....
    redirect_to user_role_path(session[:user])
  end

Not sure how pragmatic this is, but it eliminated a big ugly if/elsif/elsif/end block.

The second revelation was that I was perhaps going in the wrong direction with wanting to have the “user.<rolename>? functions, where instead I could more simply have a function to see if the user is a role. IE:

  def has_role?(role)
    return self.role.include?(role)
  end

Way better than a big long if/elsif/elsif/elsif/elsif/end block or case statement, and way more extendable.

Feel free to check out the commit on github for all the gory details.  As always any suggestions are welcome.

Related posts (maybe):

  1. Better Way To Do Dynamic Methods

Leave a Reply