Speeding up your development using HAML on your Ruby on Rails project
What Will I Learn?
In this tutorial, you will learn the HAML (HTML abstraction markup language) basics and how to speed up your development by using HAML instead of the regular HTML (in rails html.erb
files).
- You will learn how to use HAML on your Ruby on Rails project;
- You will learn the basics HTML to HAML;
- You will learn some nice tricks with HAML.
Requirements
In order to follow this tutorial you will have to fill those requirements:
- Basic HTML knowledge;
- Basic Ruby on Rails knowledge;
- A Ruby on Rails project (you can create a new one by using the
rails new haml_basics
command.
Difficulty
- Basic
Tutorial Contents
HAML (HTML abstraction markup language) is a templating engine for HTML, witch really speeds up your development since its uses almost 50% less code (using the HAML template)!
How to use HAML on your Ruby on Rails project
This step is really easy, you just have to open you Gemfile
file and add the HAML gem gem 'haml'
.
After doing it you will have to run bundle install
on your root project folder to install our newest gem. (TIP: Remember to restart your rails application after that - so it will load our new gem).
Basics HTML to HAML
Now the we have the HAML gem installed and running on our project we can start using our new template engine. Good for us, Rails won't force us to change all of ours html.erb
files into html.haml
so we can have both kinds of file on your project (TIP: would be really good if you refactor all html.erb
files into html.haml
files).
If you're like me and doesn't like to have a mix of this files (
html.erb
andhtml.haml
), you can use the haml-rails gem to convert all .erb views to haml format by using a really easy command.
I will be using a regular index.html.erb
file and I will refactor it from HTML to HAML, after that I will explain our main refactors.
These are our current HTML files:
Main file (
index.html.erb
)
<div class="container" id="main-container">
<div class="row mt-1">
<div class="col-sm-9">
<% resources.each do |resource| %>
<%= render resource %>
<% end %>
</div>
<div class="col-sm-3">
<%= render 'search' %>
</div>
</div>
</div>
Resource partial (
_resource.html.erb
)
<div class="resource mt-3">
<div class="row">
<div class="col-12">
<%= link_to resource.value, resource.url, target: '_blank' %>
<small class="badge badge-light" data-toggle="tooltip" data-active="true" data-position="top" title="Resource count">
<%= resource.total %>
</small>
</div>
</div>
<div class="row">
<div class="col-12">
<small>
<%= resource.created_at %>
</small>
<small class="ml-2">
<%= link_to '', resource_path(resource), class: 'fa fa-trash delete', method: :delete, data: { confirm: t("delete_confirm") } %>
</small>
<small class="ml-2">
<%= link_to t('edit'), edit_resource_path(resource), class: 'edit' %>
</small>
</div>
</div>
</div>
Search partial (
_search.html.erb
)
<h4 class="mt-1">
<%= t('search_header') %>
</h4>
<%= form_for @q do |f| %>
<div class="form-group">
<%= f.label :kind_eq, 'Resource kind' %>
<%= f.select :kind_eq, Resource.kinds, { prompt: t('select_all') }, { class: 'form-control' } %>
</div>
<div class="form-group">
<%= f.label :value_cont, 'Resource value' %>
<%= f.search_field :value_cont, class: 'form-control' %>
</div>
<%= f.submit class: 'btn btn-secondary' %>
<% end %>
And now the newly created HAML files:
Main file (
index.html.haml
)
.container#main-container
.row.mt-1
.col-sm-9
- resources.each do |resource|
= render 'resource'
.col-sm-3
= render 'search'
Resource partial (
_resource.html.haml
)
.resource.mt-3
.row
.col-12
= link_to resource.value, resource.url, target: '_blank'
%small.badge.badge-light{ data: { toggle: 'tooltip', active: "true", position: "top" }, title: "Resource count" }
= resource.total
.row
.col-12
%small
= resource.created_at
%small.ml-2
= link_to '', resource_path(resource), class: 'fa fa-trash delete', method: :delete, data: { confirm: t("delete_confirm") }
%small.ml-2
= link_to t('edit'), edit_resource_path(resource), class: 'edit'
Search partial (
_search.html.haml
)
%h4.mt-1
= t('search_header')
= search_form_for @q do |f|
.form-group
= f.label :kind_eq, 'Resource kind'
= f.select :kind_eq, Resource.kinds, { prompt: t('select_all') }, { class: 'form-control' }
.form-group
= f.label :value_cont, 'Resource value'
= f.search_field :value_cont, class: 'form-control'
= f.submit class: 'btn btn-secondary'
Explaining our refactoring
First of all we have to save our files using the
.haml
extension and not.erb
.
Forget the <tag></tag>
, now we have to use %tag
and we won't have to write class="class-name"
, we just have to wrote .class-name
and its almost the same for identifiers, instead of id="identifier" we just have to write
#identifier` and it's done:
Yes, you're right! HAML uses the CSS conventions (
.
for classes and#
for identifiers)
<div class="container" id="main-container">
<div class="row mt-1">
Our content here
</div>
</div>
turns into:
.container#main-container
.row.mt-1
Our content here
Yes, we won't have to write
div
since HAML uses thediv
tag as default tag, so.container
will be processed as%div.container
.
We can also add nested attributes as hash so we won't have to repeat ourself:
<small class="badge badge-light" data-toggle="tooltip" data-active="true" data-position="top" title="Resource count">
<%= resource.total %>
</small>
turns into:
%small.badge.badge-light{ data: { toggle: 'tooltip', active: "true", position: "top" }, title: "Resource count" }
= resource.total
Remember: Since we are using hash we have to follow its pattern (key: 'value', separated by commas)
Nice tricks with HAML
- HAML forces us to keep the indentation, so our code will be easier to understand
- We won't have to use the
%div
tag if we're using a class or id (HAML default tag is%div
) - We can create easier nested attributes by using a hash syntax (like:
{ first: { second: { third: 'value', fourth: 'another-value' } }
turns intofirst-second-third='value' first-second-third-fourth='another-value'
- You can use silent comments (no more comments on our HTML file) by using
-# comment here
- We won't need to close our tags, YEY!
Curriculum
This is my first Utopian tutorial! On the next tutorials I will be posting some CSS and SASS basics (using a Ruby on Rails project) tutorials.
Posted on Utopian.io - Rewarding Open Source Contributors
Hey @dpedoneze I am @utopian-io. I have just upvoted you!
Achievements
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x
Thank you for the contribution. It has been approved.
You can contact us on Discord.
[utopian-moderator]
Congratulations @dpedoneze! You have completed some achievement on Steemit and have been rewarded with new badge(s) :
You made your First Vote
You made your First Comment
Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here
If you no longer want to receive notifications, reply to this comment with the word
STOP
Do not miss the last announcement from @steemitboard!
Congratulations @dpedoneze! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!