Rails and Slim
Bài đăng này đã không được cập nhật trong 8 năm
I first encounter slim in my current project when I fixed a bug. It looks wierd and cryptic like a plain text to me without formatting whatsoever. But as I start to dig into it, it start to look more and more attractive.
What is Slim?
Slim is a template language whose goal is reduce the syntax to the essential parts without becoming cryptic.
The initial design of Slim is what you see below. It started as an exercise to see how much could be removed from a standard html template (<, >, closing tags, etc...). As more people took an interest in Slim, the functionality grew and so did the flexibility of the syntax.
What does it look like? Here it is:
doctype html
html
head
title Slim tutorial
body
h1 Heading
#content
p See what it look like, I don't know.
== yield
- unless books.empty?
table
- books.each do |book|
tr
td.title = book.title
td.price = book.price
- else
p
| No books found. Please try something else.
#footer
= render 'footer'
| Copyright © #{year} #{author}
It looks somewhat like ruby, is it not?
The code above has eliminated all closing tag, <, >, <%,div,... Make the code writing very concise but look a bit cryptic, or it is not.
2.Structure and syntax of Slim
First let install Slim. Add this to Gemfile:
gem 'slim'
gem 'slim-rails'
I think in order to make it easy for us to absorb the essence of the article, let's make a demo app.
Suppose we have the following files in app/views
,such as application.html.erb
, _footer.html.erb
, _header.html.erb
,_shim.html.erb
. We will go through each file one by one and convert it to slim.
Content of application.html.erb:
<!DOCTYPE html>
<html>
<head>
<title><%= full_title yield :title %></title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<%= render "layouts/shim" %>
</head>
<body>
<%= render "layouts/header" %>
<div class="container">
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
<%= yield %>
<%= render "layouts/footer" %>
<%= debug params if Rails.env.development? %>
Let's change it to slim now.
doctype html
html
head
title = full_title yield :title
= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true
= javascript_include_tag "application", "data-turbolinks-track" => true
= csrf_meta_tags
= render "layouts/shim"
body
= render "layouts/header"
.container
- if notice
p.alert.alert-success = notice
- if alert
p.alert.alert-danger = alert
= yield
= render "layouts/footer"
= debug params if Rails.env.development?
There are a lot going on here. So one thing obvious is that there is no closing tag.
doctype html
--> DOCTYPE! html
html
--> <html> </html>
head
--> <head> </head>
title
--> <title> </title>
body
--> <body> </body>
Indentation is very important and is keeped the same as before converting.
you may notice =
sign. It equals to rails syntax <%= %>
.
So something like <%= render "layouts/header" %>
is equivalent to = render "layouts/header"
.
You might also notice -
sign. This denotes control code. Examples of control code are loops and conditionals. Blocks are defined only by indentation. So this does not display the result.
It equivalent to rails <% %>
.
So something like - if notice
is equivalent to <% if notice %>
. A trailing space behind -
is necessary.
A nice short .
is for class. So .container
is equivalent to <div class="container">
.
and p.alert.alert-danger
--> <p class="alert alert-danger">
. Notice that there is no space between p
and alert
.
Let look at some more files:
Content of header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<%= link_to "test app", "#", id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li> <%= link_to "Help", help_path %></li>
<li> <%= link_to "Home", root_path %></li>
<li>
<% if user_signed_in? %>
<li><%= link_to "Tests", tests_path %></li>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<%= current_user.name %> <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", edit_user_registration_path(current_user) %></li>
<li class="divider"></li>
<li>
<%= link_to "Sign out", destroy_user_session_path, method: :delete %>
</li>
</ul>
</li>
<% else %>
<li><%= link_to "Sign in", new_user_session_path %></li>
<% end %>
</li>
</ul>
</nav>
</div>
</header>
is converted to header.slim
with the following content:
header.navbar.navbar-fixed-top.navbar-inverse
.container
= link_to "test app", "#", id: "logo"
nav
ul.nav.navbar-nav.navbar-right
li = link_to "Help", help_path
li = link_to "Home", root_path
li
- if user_signed_in?
= link_to "Tests", tests_path
li#fat-menu.dropdown
a.dropdown-toggle href="#" data-toggle="dropdown"
= current_user.name
b.caret
ul.dropdown-menu
li = link_to "Profile", current_user
li = link_to "Settings", edit_user_registration_path(current_user)
li.divider
li = link_to "Sign out", destroy_user_session_path, method: :delete
- else
li = link_to "Sign in", new_user_session_path
li#fat-menu.dropdown
in the above code is equivalent to <li id="fat-menu" class="dropdown"></li>
.
#
is for id
.
let see another file footer.html.erb
and change it to footer.slim
.
<footer class="footer">
<small>
<a href="http://railtutorial.org"> Rails Tutorial</a> by Michael Hartl
</small>
<nav>
<ul>
<li><%= link_to "About", about_path %></li>
<li><%= link_to "Contact", contact_path %></li>
<li><%= link_to "News", news_path %></li>
</ul>
</nav>
</footer>
is converted to:
footer.footer
small
a> href="http://railtutorial.org" Rails Tutorial
' by Michael Hartl
nav
ul
li = link_to "About", about_path
li = link_to "Contact", contact_path
li = link_to "News", news_path
Do you notice a>
? Why >
there? >
add a trailing space after the link, So that "Rails Tutorial" is not stuck with "by Michael Hartl".
And how about '
sign? It is verbatim text with trailing white space. The single quote tells Slim to copy the line, but makes sure that a single trailing white space is appended.
Last file shim.html.erb
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
is converted to
/[if lt IE 9]
script src="http://html5shim.googlecode.com/svn/trunk/html5.j"
This is called "IE conditional comment"
I hope you get a glimpse of slim. There are still more advanced features to explore such as helper, capturing, include and so on. You can start to implement it in your project.
All rights reserved