08
Jul
09

DRY Views in Rails with Blocks

I’m a fan of the DRY (Don’t Repeat Yourself) principal. I think that computers were invented for a reason and that reason was not so that I could do the same thing over and over. If it’s one thing that computers do well, it’s doing the exact same thing ad nauseum. So, I do as much as I can in order not to repeat myself a lot when coding.

I have an case now where within the main portion where content is rendered sometimes there separate content on the right side, and sometimes there is not. For example, with no content on the right side, it looks like so:

  <div id="left">
    I am left content
  </div>

Simple enough, but when there is content on the right side, the left side has to get a little smaller, so there is a class added called “with_left” to the left div that makes the width less to accommodate the right content.

  <div id="right">
    I am right content
  </div>
  <div id="left" class="with_right">
    I am left content
  </div>

The problem comes in when the right content is different from page to page and I’m not exactly sure if there is going to be any right content to begin with, as it relies on some dynamic data. Sure, I could do something like this for every page, but I would get annoying fast, and I’m sure there would be one instance where I would forget to do it the right way:

  <% if right_content %>
    <div id="right">
      <%= right_content %>
    </div>
  <% end %>
  <div id="left" <%= 'class="with_right"' if right_content -%>>
    I am left content
  </div>

So, in comes Ruby to the rescue. I heart blocks and I’m glad that ruby has them, because this is a great case where they come in handy. Instead of doing the above logic over and over again, I can create a method called main_content that allows me to do this in a more generic way.

  def main_content(params={},&amp;block)
    right_content = params[:right_content]
    unless right_content.blank?
      right_div = <<-HTML
        <div id="right">
          #{right_content}
        </div>
      HTML
      concat(right_div)
      concat('<div id="left" class="with_right">')
    else
      concat('<div id="left">')
    end
    yield
    concat('</div>')
  end

Now I can use this method like so:


  <% main_content(:right_content=>render(:partial=>'account_actions')) do %>
    <h3>Edit Account</h3>
  <% end >%

If the partial account_actions renders anything, I will get this:

  <div id="right">
    Output of account_actions partial
  </div>
  <div id="left" class="with_right">
    <h3>Edit Account</h3>
  </div>

If the account_actions partial doesn’t end up rendering anything, then I get:

  <div>
    <h3>Edit Account</h3>
  </div>

Nice! Everything looks good, so I can start adding some tests to it. Here’s how I tested it with rspec:

  describe 'main content renderer' do
    
    before do
      @buffer = ""
      stub!(:output_buffer).and_return(@buffer)
    end
    
    it 'will render only the left div when there is no right content' do
      main_content{}
      output_buffer.should have_tag("div#left")
    end
    
    it 'will put the yielded content in the left div' do
      main_content{concat("Yielded content")}
      output_buffer.should have_tag("div#left","Yielded content")
    end
    
    it 'will display the right content in the right div if there is any' do
      main_content(:right_content=&gt;'Right'){}
      output_buffer.should have_tag("div#right","Right")
    end
    
    it 'will add a class of "with_right" to the left div if there is right content' do
      main_content(:right_content=&gt;'Right'){}
      output_buffer.should have_tag("div#left.with_right")
    end
    
  end


0 Responses to “DRY Views in Rails with Blocks”



  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Stay Updated

or

Get new posts via email

Software Blogs - BlogCatalog Blog Directory

 

July 2009
M T W T F S S
« Jun    
 12345
6789101112
13141516171819
20212223242526
2728293031  

Follow

Get every new post delivered to your Inbox.