This article is deprecated.I've marked this article as deprecated. It is either because the gem or plugin discussed in this article is no longer maintained, or I've changed my opinion on it. This article is here only as an historic reference.
Ruby on Rails is a fine framework. It uses Ruby which is beautiful programming language. Everything is an object in Ruby, and the block structure allows you to do marvelous stuff with it. The Rails team is well aware of this and uses it, making Rails a great partner in crime. I still remember the first time I viewed the migration for creating a new database table:
create_table "users" do |t| t.column :name, :string, :limit => 40 t.column :email, :string # etc end
I almost didn't recognize it at first. I didn't know Ruby back then, I just did what was necessary to make it work without looking at what it does. But take a good look at what it really does. It creates a table and gives you an object for you to play with. Within the block you can edit the properties of the thing you're creating in small readable lines. Ruby itself is full of these functions. Iterators are probably the best examples. What would any Ruby programmer do without each, select and sort? These blocks are arguably one of the nicest features in Ruby.
It's good to know that Rails incorporates this feature. Although I find it lacking in the view part. Sure you'll use methods like
each, but think of all the helper-methods out there. Usually they are single methods doing some stuff and returning some HTML. Nice, but a bit cumbersome. Not that you'd need anything more complicated for creating a link or an image, but there is hardly anything 'sweet' going on in the views.
Then there are forms. Forms form the center of any web application, certainly Rails-made applications. In the views at least. Rails gives us the form_for and form_tag methods. These work in rather the same way as the migrations, giving you an form-object to play with. With this form object you can create all kinds of fields. Consider this simple form:
<% form_for(@user) do |form| %> <p> <%= form.label(:name, 'your name:') %> <%= form.text_field(:name) %> </p> <p> <%= form.label(:password, 'your password:') %> <%= form.password_field(:password) %> </p> <% end %>
<%= form.create_field(:name) do |field| field.type = :text_field field.label = 'Name' field.required! field.description = 'Please enter your name here. It may only contain alphanumeric characters and underscores' end %> <%= form.create_field(:category_ids) do |field| field.label = 'Select some categories' field.type = :checkboxes field.add_options do |opt| opt.add 1, 'foo' opt.add 2, 'bar' end end %>
I hope you agree with me that this is much more readable and editable. It trades of long lines for more shorter lines which is a good trade-off. If you're using Haml for your views it's even more important to have short lines than in ERB. In Haml you can't easily break up lines so short lines of code is vital to the readability of your views. Views naturally have the tendency to become hard to follow and ugly, so it is recommended that important and complex parts of it (mainly views) stay easy and readable. Readability helps your maintainability. I am currently making this kind of form builder, so if you have any suggestions, please do!
But why stop here? Forms are not the only part which involves a lot of HTML and repetitive coding. Website often include blocks in a sidebar which are totally suited for this kind of solution. These are the days of glossy website designs, in the world of Web 2.0 every angle is softened or rounded. Sometimes this asks for a lot of HTML, building divs into divs. I'm a fan of Haml for making this easy, but you need a way to shorten lines, and in some way 'metaprogram' your HTML. At the risk of sounding 'Java-ish', I'd say it would be better to build an extra layer of abstraction into the so trusty MVC. In your view you decide what goes where, what your lines are and which fields are available. Above it lies an HTML layer which translates it to whatever your website is designed to look like. A view gets split in two: a structural layer and a design layer. If thought out well you can even change one layer without the need to change the other.
This might not be your solution. Your website might be too small to make such a difference. But it's worth thinking about it when you're building something. If you're making a helper-method, and you find yourself in need of a lot (say, more than 2) arguments, consider making a small object with some accessors to making this easy. Here is something to help you on your way:
# in your view, traditional way (which can get very long, depending on the number of arguments): <%= small_menu(:title => 'Monkey', :foo => 'bar') %> # with a small helper class and a block structure it may become: <%= small_menu do |sm| sm.title = 'Monkey' sm.foo = 'bar' end %>
# you'll need this in your helper for that: module SomeHelper def small_menu sm = SmallMenu.new yield sm # construct your html here, using parameters from the sm-object end end # in the same helper (only if it's short) or in another file (helper or lib) class SmallMenu attr_accessor :title, :link, :partial, :foo end
By the way, if you haven't seen it yet, you should watch Railscast episode 101 for another nice way to incorporate classes into your helpers.