Textmate+Rails: Easy partials for better code

22 December 2006

As you may know, I use TextMate for editing Rails code.

I’ve just been browsing the Rails bundle today and I came across some very interesting things. Today I’ll tell you about partials.

Partials are ERb templates. They are mostly HTML (or RJS or XML or whatever output format you use) and include some embedded Ruby to show actual content. Partials are not linked to a method in a controller, but instead they can be easily rendered through-out your application.

TextMate allows you to refactor your application to use partials with almost no effort!

First something about partials for those who don’t know about it.

Partials are stored in files that start with an _ (underscore) and end in .rthml (or .rjs or .rxml) and you may include them in your ERb like this:

< %= render :partial => 'userinfo' %>

This will include the partial _userinfo.rhtml for you. This way you can avoid duplication by including the same ERb template (partial) over and over again.

Partials are also useful to keep your views (templates) clean and easy to understand. In large projects this will allow you later to easily change a view without having to spit through 500 lines of ERb.

Let’s say you have a profile page where you want to show a users’s profile and some options for when the user is viewing his own profile. Also, you want to show a simple message when the users has not yet created a profile, which is a possibility in my application. The show.rhtml template for the profile may look like this

Profile for < %=h @profile.user.login %>

< % if @profile.exists? -%>
< %= @profile.firstname %> has been a member for < %= distance_of_time_in_words_to_now @profile.user.created_at %>

General information

Name: < %= @profile.fullname %>
Country: < %= @profile.country %>
Birthday: < %= fmt_date @profile.birthday %>

About < %= @profile.firstname %>

< %= markdown @profile.about %>
< % else -%>
< %= @profile.user.login %> has been a member for < %= distance_of_time_in_words_to_now @profile.user.created_at %>

Oh my!

This user has not yet created a profile.

< % end -%> < % if @profile.user.id == current_user.id -%>

Options

This is your profile, so you have some options:

  • < %= link_to "Change password", :controller => 'account', :action => "change_password" %>
  • < %= link_to "Edit your profile", profile_edit_url(:login => current_user.login) %>
< % end -%>

As you may see, this is chaos. It’s not easy to read and you can’t easily change something when you need to. Wouldn’t it be great to store all three seperate blocks (profile, no profile message and options) in partials?

This is where TextMate does it’s magic. Here’s a before snaphot:

before.png

Now, select the part between the if and else statements. This is where a normal profile is shown. Next, use TextMate: SHIFT-CTRL-H. You’ll get a pop-up asking you how you’d like to name the partial. In this case I choose ‘profile’.

during.png

After you click OK, the partial will be created containing the code you selected and an appropriate render method is placed instead. This is what the code looks like after:

after.png

After all this the same ERb template looks like this:

Profile for < %=h @profile.user.login %>

< % if @profile.exists? -%> < %= render :partial => 'profile' %> < % else -%> < %= render :partial => 'noprofile' %> < % end -%> < % if @profile.user.id == current_user.id -%> < %= render :partial => 'options' %> < % end -%>

Now, isn’t that more readable? Even, if you want to change a profile, you can just edit _profile.rhtml and you’re done.