ActiveHelper + Rails is no pain in the ass!

Recently (about 6 minutes ago) I added support for Rails in ActiveHelper. The library as-it is still completely independent from any MVC framework and simply provides a generic helper API.

However, we got some Rails bindings now.

If you’re not yet familiar with ActiveHelper, no problem, it’s brandnew. Consider skimming the introducing post first. Or directly jump to the github repository.

Writing the helper

Let’s assume you want to create a new helper to replace the #link_to method. Why not name it LinkingHelper?

class LinkingHelper < ActiveHelper::Base
  provides :link_for
 
  def link_for(title, url)
    '<a href="' + url + '">' + title + '</a>'
  end
end

You’d put this into app/active_helpers/linking_helper.rb.

Preparing the controller

Bla bla bla, it’s obvious how to use ActiveHelpers in controllers.

class BlogController < ActionController::Base
  active_helper LinkingHelper
 
  def show
    @post = Post.find params[:id]
  end
end

Helping the view

As soon as the controller did include the LinkingHelper its provided methods are around in the view.

1
2
3
4
5
6
Bookmarkable link: <%= link_for @post.title, @post.url %>
 
<h1><%= @post.title %></h1>
<p>
  <%= @post.body %>
</p>

You used your #link_for to generate a link in line 1.

So… where’s the benefit?

Being a good programmer you instantly decide to extract the markup logic from the LinkingHelper to some separate MarkupHelper.

The latter would provide a method #tag for generating markup.

Your former helper now looks like this.

1
2
3
4
5
6
7
class LinkingHelper < MarkupHelper
  provides :link_for
 
  def link_for(title, url)
    tag(:a, title, :href => url)
  end
end

Noticed the inheritance in line 1? Wow- that’s OOP features in helpers. Nice.

Reusing old-school helpers

Now what if you still want to use #url_for to setup the link address? It’s hidden somewhere in Rails gloomy mixin magic.

You know it’s floating around in your view. So go and use it.

1
2
3
4
5
6
7
8
9
class LinkingHelper < MarkupHelper
  provides :link_for
  needs :url_for
 
  def link_for(title, url)
    url = url_for(url)
    tag(:a, title, :href => url)
  end
end

Step-by-step, dude. You simply use #url_for in line 6. Your helper knows about it since you defined the dependency (line 3).

That’s gonna work- but… why?

Well, any ActiveHelper simply delegates dependencies back to where it was imported into. In our case, any call to #url_for is routed to the ActionView instance which has to care about that.

Delegation for a better world

The new keywords in the Helper World are delegation and interfaces.

Besides that, we got back OOP and inheritance to helpers.

Lemme end this boring post by quoting Manuel who’s just diving into ActiveHelpers.

It’s funny- ActiveHelpers is nothing more than 80 lines of code. Anyway, it’s forcing you to write clean code… in a gentle way!

Isn’t that great?

Leave a Reply