(For more resources related to this topic, see here.)
Let's create a simple rails application and change one of the view files to Haml from ERB:
rails new blog
bundle install
rails g scaffold post
rake db:migrate
You should get an output as shown in the following screenshot:
Our application is not yet generating Haml views automatically. We will switch it to this mode in the next steps.
The index.html.erb file that has been generated and is located in app/views/posts/index.html.erb looks as follows:
<h1>Listing posts</h1>
<table>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
<% @posts.each do |post| %>
<tr>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm:
'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br>
<%= link_to 'New Post', new_post_path %>]
Let's convert it to an Haml view step-by-step. First, let's understand the basic features of Haml:
Knowing the previous features we can write the first lines of our example view in Haml. Open the index.html.erb file in an editor and replace <h1>, <table>, <th>, and <tr> as follows:
After those first replacements our view file should look like:
%h1 Listing posts
%table
%tr
%th
%th
%th
<% @posts.each do |post| %>
<tr>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm:
'Are you sure?' } %></td>
</tr>
<% end %>
<br>
<%= link_to 'New Post', new_post_path %>
Please notice how %tr is nested within the %table tag using a tab and also how %th is nested within %tr using a tab.
Next, let's convert the Ruby parts of this view. Ruby is evaluated and its output is inserted into the view when using the equals character. In ERB we had to use <%=, whereas in Haml, this is shortened to just a =. The following examples illustrate this:
Please note that you have to leave a space after the equals sign. After the changes are incorporated, our view file will look like
%h1 Listing posts
%table
%tr
%th
%th
%th
<% @posts.each do |post| %>
%tr
%td= link_to 'Show',post
%td= link_to 'Edit',edit_post_path(post)
%td= link_to 'Destroy',post,method: :delete,data: { confirm: 'Are
you sure?' }
%br/
= link_to 'New Post',new_post_path
The only thing left to do now is to convert the Ruby block part: <% @posts.each do | post | %>. Code that needs to be run, but does not generate any output, is written using a hyphen character. Here is how this conversion works:
After we replace the remaining part in our view file according to the previous rules, it should look as follows:
%h1 Listing posts
%table
%tr
%th
%th
%th
- @posts.each do |post|
%tr
%td= link_to 'Show', post
%td= link_to 'Edit', edit_post_path(post)
%td= link_to 'Destroy', post, method: :delete, data: { confirm:
'Are you sure?' }
%br/
= link_to 'New Post', new_post_path
Save the view file and change its name to index.html.haml. This is now an Haml-based template. Start our example Rails application and visit http: //localhost:3000/posts to see the view being rendered by Rails, as shown in the following screenshot:
In the previous step, we have enabled Haml in the test application. However, if you generate new view files using any of the Rails built-in generators, it will still use ERB.
Let's switch the application to use Haml as the templating engine.
Edit the blog application Gemfile and add a gem named haml-rails to it. You can add it to the :development group because the generators are only used during development and this functionality is not needed in production or test environments.
Our application Gemfile now looks as shown in the following code:
source 'https://rubygems.org'
gem 'rails', '3.2.13'
gem 'sqlite3'
gem 'haml'
gem 'haml-rails', :group => :development
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
Then run following bundle command to install the gem:
bundle install
Let's say the posts in our application need to have categories. Run the scaffold generator to create some views for categories. This generator will create views using Haml, as shown in the following screenshot:
Please note that new views have a .html.haml extension and are using Haml. For example, the _form.html.haml view for the form looks as follows:
= form_for @category do |f|Asjd12As
- if @category.errors.any?
#error_explanation
%h2= "#{pluralize(@category.errors.count, "error")} prohibited
this category from being saved:"
%ul
- @category.errors.full_messages.each do |msg|
%li= msg
.actions
= f.submit 'Save'
There are two very useful shorthand notations for creating a <div> tag with a class or a <div> tag with an ID.
To create a div with an ID, use the hash symbol followed by the name of the ID. For example, #error_explanation will result in <div id="error_explanation">
To create a <div>tag with a class attribute, use a dot followed by the name of the class. For example, .actions will create <div class="actions">
Our example blog app still has some leftover templates which are using ERB as well as an application.html.erb layout file. We would like to convert those to Haml. There is no need to do it all individually, because there is a handy gem which will automatically convert all the ERB files to Haml, shown as follows:
gem install html2haml
for file in $(find . -type f -name \*.html.erb); do
html2haml -e ${file} "$(dirname ${file})/$(basename ${file}
.erb).haml";
done
find ./ -name *erb | while read line; do rm $line; done
This article covered integrating with Rails and creating a simple view file, switching Rails application to use Haml as the templating engine, and converting existing view templates to Haml.
Further resources on this subject: