Speeding up your development using HAML on your Ruby on Rails project

in #utopian-io6 years ago (edited)

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 and html.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 the div 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 into first-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

Sort:  

Hey @dpedoneze I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • This is your first accepted contribution here in Utopian. Welcome!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

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

Upvote this notification to help all Steemit users. Learn why here!

Do not miss the last announcement from @steemitboard!

Congratulations @dpedoneze! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 1 year!

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!

Coin Marketplace

STEEM 0.20
TRX 0.12
JST 0.029
BTC 61440.52
ETH 3447.43
USDT 1.00
SBD 2.52