[RUBY] Try changing the .erb file to .slim

environment

Ruby 2.5.7 Rails 5.2.4

Background

I'm using .erb as the Rails template engine, but there are other template engines such as .haml and .slim. This time I was interested in .slim, I changed a part of the existing .erb file to .slim and confirmed the operation, so I will write the process. It will be almost a case study, so please refer to it.

Basic syntax

The basic changes are as follows.

slim:example.html.slim


/Only the start tag, not the end tag
<body></body>
=>
body

<h1>title</h1>
=>
h1 title

/id name class name is written continuously
<ul class="list"></ul>
=>
ul.list

<span id="btn"></span>
=>
span#btn

/div omits even div
<div id="main-contents" class="flex container" ></div>
=>
#main-contents.flex.container

/ruby code<%= %>Is omitted(=What is=Just write)
<%= link_to 'next' %>
=>
= link_to 'next'

/ <% %> =Those without is at the beginning-Put on
/ <% end %>Are all omitted (loop statements, etc.)
<%if conditional statement%>
<% else %>
<% end %>
=>
-if conditional statement
- else

See here for syntax details. GitHub - slim Qiita --Quick Learning Template Slim (HTML Creation) Qiita-HTML template engine of Rails, basic notation of Slim Qiita-[Learn at explosive speed] From how to use slim with Rails to basic grammar

Compare .erb and .slim in real code

From here, I will introduce the following 4 types of files that I actually changed in before / after format. *application.html.erb/slim *_form.html.erb/slim *new.html.erb/slim *edit.html.erb/slim

These View files are also available on my GitHub. GitHub - matchi_ver.slim application.html

erb:application.html.erb


<!DOCTYPE html>
<html lang="ja">
<head>
  <%= favicon_link_tag('favicon.ico') %>
  <%= favicon_link_tag 'home-icon.png', rel: 'apple-touch-icon', size: '180x180', type: 'image/png' %>
  <%= favicon_link_tag 'home-icon.png', rel: 'android-touch-icon', size: '192x192', type: 'image/png' %>
  <title>Matchi</title>
  <script src="//maps.google.com/maps/api/js?key=<%= ENV['GOOGLE_PLATFORM_API_KEY'] %>"></script>
  <%= include_gon %>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application' %>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet">
  <!-- Global site tag (gtag.js) - Google Analytics -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=<%= ENV['GOOGLE_ANALYTICS_TRACKING_ID'] %>"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());

    gtag('config', "<%= ENV['GOOGLE_ANALYTICS_TRACKING_ID'] %>");
  </script>
</head>

<body>
<header>
  <div class="header-container">
    <%#PC screen header%>
    <div class="flex pc-header">
      <%= link_to root_path do %>
        <div class="logo-image"></div>
      <% end %>
      <div class="header-nav">
        <nav>
          <ul class="flex header-ul">
            <% url = request.fullpath %>
            <%#to url'owner'If there is a store header%>
            <% if url.include?('owner') %>
              <% if master_admin_signed_in? %>
                <li><%= link_to 'Top administrator', new_master_admin_session_path %></li>
                <li><%= link_to 'Admin log out', destroy_master_admin_session_path, method: :delete %></li>
              <% end %>
              <% if owner_restaurant_signed_in? %>
                <li><%= link_to 'Store top', owner_restaurant_path(current_owner_restaurant) %></li>
                <li><%= link_to 'Store logout', destroy_owner_restaurant_session_path, method: :delete %></li>
              <% end %>
              <% if public_user_signed_in? %>
                <li><%= link_to 'General member TOP', mypage_path(current_public_user) %></li>
                <li><%= link_to 'General member logout', destroy_public_user_session_path, method: :delete %></li>
              <% else %>
                <li><%= link_to 'General member login', new_public_user_session_path %></li>
              <% end %>

            <%#to url'master'Admin header, if any%>
            <% elsif url.include?('master') %>
              <% if master_admin_signed_in? %>
                <li><%= link_to 'New store registration', new_owner_restaurant_registration_path %></li>
                <li><%= link_to 'Top administrator', new_master_admin_session_path %></li>
                <li><%= link_to 'Admin log out', destroy_master_admin_session_path, method: :delete %></li>
              <% end %>
              <% if public_user_signed_in? %>
                <li><%= link_to 'General member TOP', mypage_path(current_public_user) %></li>
                <li><%= link_to 'General member logout', destroy_public_user_session_path, method: :delete %></li>
              <% else %>
                <li><%= link_to 'General member login', new_public_user_session_path %></li>
              <% end %>
              <% if owner_restaurant_signed_in? %>
                <li><%= link_to 'Store top', owner_restaurant_path(current_owner_restaurant) %></li>
                <li><%= link_to 'Store logout', destroy_owner_restaurant_session_path, method: :delete %></li>
              <% else %>
                <li><%= link_to 'Store login', new_owner_restaurant_session_path %></li>
              <% end %>

            <%#Other than the above, header for general users%>
            <% else %>
              <% if master_admin_signed_in? && owner_restaurant_signed_in? %>
                <li><%= link_to 'Top administrator', new_master_admin_session_path %></li>
                <li><%= link_to 'Admin log out', destroy_master_admin_session_path, method: :delete %></li>
                <li><%= link_to 'Store TOP', owner_restaurant_path(current_owner_restaurant) %></li>
                <li><%= link_to 'Store logout', destroy_owner_restaurant_session_path, method: :delete %></li>
              <% elsif owner_restaurant_signed_in? %>
                <li><%= link_to 'Store TOP', owner_restaurant_path(current_owner_restaurant) %></li>
                <li><%= link_to 'Store logout', destroy_owner_restaurant_session_path, method: :delete %></li>
              <% elsif master_admin_signed_in? %>
                <li><%= link_to 'Top administrator', new_master_admin_session_path %></li>
                <li><%= link_to 'Admin log out', destroy_master_admin_session_path, method: :delete %></li>
                <li><%= link_to 'Store login', new_owner_restaurant_session_path %></li>
              <% end %>
              <% if public_user_signed_in? %>
                <li><%= link_to 'MyPage', mypage_path(current_public_user) %></li>
                  <%# if alert.count >= 1 %>
                    <li><%#= link_to 'I have news.' %></li>
                  <%# end %>
                <li><%= link_to 'Log out', destroy_public_user_session_path, method: :delete %></li>
              <% else %>
                <li><%= link_to 'sign up', new_public_user_registration_path %></li>
                <li><%= link_to 'Login', new_public_user_session_path %></li>
              <% end %>
            <% end %>
          </ul>
        </nav>
      </div>
    </div>

    <%#Smartphone screen header%>
    <div class="flex sp-header">
      <div class="hamburger">
        <span class="bar bar-top"></span>
        <span class="bar bar-center"></span>
        <span class="bar bar-bottom"></span>
      </div>
    <%= link_to root_path do %>
      <div class="logo-image"></div>
    <% end %>
      <%#Notification of unread notifications%>
      <div class="alert">
        <i id="alert-bell" class="fa-2x far fa-bell"><div class="hidden icon"></div></i>
      </div>
      <%#Hamburger menu%>
      <div class="hamburger-menu">
        <ul>
          <% if public_user_signed_in? %>
            <li><%= link_to 'MyPage', mypage_path(current_public_user) %></li>
          <% else %>
            <li><%= link_to 'sign up', new_public_user_registration_path %></li>
            <li><%= link_to 'Login', new_public_user_session_path %></li>
          <% end %>
          <li><%= link_to 'Service introduction', about_path %></li>
          <li><%= link_to 'Restaurant list', public_restaurants_path %></li>
          <li><%= link_to 'Menu list', public_menus_path %></li>
          <% if public_user_signed_in? %>
            <li><%= link_to 'Log out', destroy_public_user_session_path, method: :delete %></li>
          <% end %>
        </ul>
      </div>
    </div>
  </div>
</header>

<main>
  <div class="body-container">
    <%= yield %>
  </div>
</main>

<footer>
  <div class="flex footer-container">
    <%= link_to root_path do %>
      <div class="logo-image"></div>
    <% end %>
    <div class="footer-menu">
      <ul class="footer-links">
        <li><%= link_to 'Contact Us', contacts_new_path %></li>
        <li><%= link_to 'Terms of service', terms_path %></li>
        <li><%= link_to 'privacy policy', privacy_path %></li>
        <li><%= link_to 'Operator information', admin_path %></li>
      </ul>
    </div>
  </div>
  <div class="copyright">
    <small>©︎ 2020 MasaoSasaki</small>
  </div>
  <div id="move-head">
    <div class="circle move-head"><i class="fa-2x fas fa-arrow-up"></i></div>
  </div>
</body>
</footer>
</html>

slim:application.html.slim


doctype html
html lang="ja"
  head
    = favicon_link_tag('favicon.ico')
    = favicon_link_tag 'home-icon.png', rel: 'apple-touch-icon', size: '180x180', type: 'image/png'
    = favicon_link_tag 'home-icon.png', rel: 'android-touch-icon', size: '192x192', type: 'image/png'
    title Matchi
    script src="//maps.google.com/maps/api/js?key=#{ENV['GOOGLE_PLATFORM_API_KEY']}"
    = include_gon
    = csrf_meta_tags
    = csp_meta_tag
    = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
    = javascript_include_tag 'application'
    meta name="viewport" content="width=device-width,initial-scale=1"
    link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet"
    / Global site tag (gtag.js) - Google Analytics
    javascript: async src="https://www.googletagmanager.com/gtag/js?id=#{ENV['GOOGLE_ANALYTICS_TRACKING_ID']}"

  body
    header
      .header-container
        /PC screen header
        .flex.pc-header
          = link_to root_path
            .logo-image
          .header-nav
            nav
              ul.flex.header-ul
                - url = request.fullpath
                /to url'owner'If there is a store header
                - if url.include?('owner')
                  - if master_admin_signed_in?
                    li = link_to 'Top administrator', new_master_admin_session_path
                    li = link_to 'Admin log out', destroy_master_admin_session_path, method: :delete
                  - if owner_restaurant_signed_in?
                    li = link_to 'Store top', owner_restaurant_path(current_owner_restaurant)
                    li = link_to 'Store logout', destroy_owner_restaurant_session_path, method: :delete
                  - if public_user_signed_in?
                    li = link_to 'General member TOP', mypage_path(current_public_user)
                    li = link_to 'General member logout', destroy_public_user_session_path, method: :delete
                  - else
                    li = link_to 'General member login', new_public_user_session_path
                /to url'master'Admin header, if any
                - elsif url.include?('master')
                  - if master_admin_signed_in?
                    li = link_to 'New store registration', new_owner_restaurant_registration_path
                    li = link_to 'Top administrator', new_master_admin_session_path
                    li = link_to 'Admin log out', destroy_master_admin_session_path, method: :delete
                  - if public_user_signed_in?
                    li = link_to 'General member TOP', mypage_path(current_public_user)
                    li = link_to 'General member logout', destroy_public_user_session_path, method: :delete
                  - else
                    li = link_to 'General member login', new_public_user_session_path
                  - if owner_restaurant_signed_in?
                    li = link_to 'Store top', owner_restaurant_path(current_owner_restaurant)
                    li = link_to 'Store logout', destroy_owner_restaurant_session_path, method: :delete
                  - else
                    li = link_to 'Store login', new_owner_restaurant_session_path
                /Other than the above, header for general users
                - else
                  - if master_admin_signed_in? && owner_restaurant_signed_in?
                    li = link_to 'Top administrator', new_master_admin_session_path
                    li = link_to 'Admin log out', destroy_master_admin_session_path, method: :delete
                    li = link_to 'Store TOP', owner_restaurant_path(current_owner_restaurant)
                    li = link_to 'Store logout', destroy_owner_restaurant_session_path, method: :delete
                  - elsif owner_restaurant_signed_in?
                    li = link_to 'Store TOP', owner_restaurant_path(current_owner_restaurant)
                    li = link_to 'Store logout', destroy_owner_restaurant_session_path, method: :delete
                  - elsif master_admin_signed_in?
                    li = link_to 'Top administrator', new_master_admin_session_path
                    li = link_to 'Admin log out', destroy_master_admin_session_path, method: :delete
                    li = link_to 'Store login', new_owner_restaurant_session_path
                  - if public_user_signed_in?
                    li = link_to 'MyPage', mypage_path(current_public_user)
                      / if alert.count >= 1
                          li = link_to 'I have news.'
                    li = link_to 'Log out', destroy_public_user_session_path, method: :delete
                  - else
                    li = link_to 'sign up', new_public_user_registration_path
                    li = link_to 'Login', new_public_user_session_path
        /Smartphone screen header
        .flex.sp-header
          .hamburger
            span.bar.bar-top
            span.bar.bar-center
            span.bar.bar-bottom
          = link_to root_path
            .logo-image
          /Notification of unread notifications
          .alert
            i#alert-bell.fa-2x.far.fa-bell
              .hidden.icon
          /Hamburger menu
          .hamburger-menu
            ul
              - if public_user_signed_in?
                li = link_to 'MyPage', mypage_path(current_public_user)
              - else
                li = link_to 'sign up', new_public_user_registration_path
                li = link_to 'Login', new_public_user_session_path
              li = link_to 'Service introduction', about_path
              li = link_to 'Restaurant list', public_restaurants_path
              li = link_to 'Menu list', public_menus_path
              - if public_user_signed_in?
                li = link_to 'Log out', destroy_public_user_session_path, method: :delete
    main
      .body-container == yield
    footer
      .flex.footer-container
        = link_to root_path
          .logo-image
          .footer-menu
            ul.footer-links
              li = link_to 'Contact Us', contacts_new_path
              li = link_to 'Terms of service', terms_path
              li = link_to 'privacy policy', privacy_path
              li = link_to 'Operator information', admin_path
      .copyright
        small ©︎ 2020 MasaoSasaki
      #move-head
        .circle.move-head
          i.fa-2x.fas.fa-arrow-up

new.html

erb:new.html.erb


<div class="contents menus-new">
  <h2>Menu addition</h2>
  <%= render partial: 'form', locals: {
    restaurant: @restaurant,
    menu: @menu,
    tags: @tags,
    menu_tags: @menu_tags,
    path: owner_restaurant_menus_path,
    truth: false, submit: 'Create'
  } %>
</div>

slim:new.html.slim


.contents.menus-new
h2 menu added
  == render 'form',
    restaurant: @restaurant,
    menu: @menu,
    tags: @tags,
    menu_tags: @menu_tags,
    path: owner_restaurant_menus_path,
    truth: false, submit: 'Create'

edit.html

erb:edit.html.erb


<div class="contents menus-edit">
  <h2 class="menus-edit-h2">Menu editing</h2>
  <%= render partial: 'form', locals: {
    restaurant: @restaurant,
    menu: @menu,
    tags: @tags,
    menu_tags: @menu_tags,
    path: owner_restaurant_menu_path,
    truth: true, submit: 'update'
  } %>
</div>

slim:edit.html.slim


contents.menus-edit
  h2.menus-edit-h2 menu edit
  == render 'form',
    restaurant: @restaurant,
    menu: @menu,
    tags: @tags,
    menu_tags: @menu_tags,
    path: owner_restaurant_menu_path,
    truth: true, submit: 'update'

_form.html

erb:_form.html.erb


<div class="menu-form">
  <%= form_with model: [restaurant, menu], url: path, local: true do |f| %>
    <section class="menu-status">
      <div class="menu-form1">
        <h3>Menu details</h3>
        <table>
          <tbody>
            <tr>
              <td><%= f.label :title, value: 'Menu name' %></td>
              <td><%= f.text_field :title %></td>
            </tr>
            <tr>
              <td><%= f.label :regular_price, value: 'Regular price (excluding tax):' %></td>
              <td><%= f.number_field :regular_price %>Circle</td>
            </tr>
            <tr>
              <td><%= f.label :discount_price, value: 'Offer price (excluding tax):' %></td>
              <td><%= f.number_field :discount_price %>Circle</td>
            </tr>
            <tr>
              <td><%= f.label :reservation_method, value: 'Reservation method' %></td>
              <td><%= f.select :reservation_method, Menu.reservation_methods.keys.map {|method| [method]} %></td>
            </tr>
            <tr>
              <td><%= f.label :is_sale_frag, value: 'Sales status' %></td>
              <td><%= f.select :is_sale_frag, [['Sale', true], ['Suspended', false]] %></td>
            </tr>
          </tbody>
        </table>
      </div>
      <div class="menu-form2">
        <h3>Menu image</h3>
        <div class="menu-image">
          <%= f.attachment_field :menu_image %>
          <div class="image-preview"></div>
          <h4>Add tag (optional)</h4>
          <%= text_field_tag :tag_name %>
          <%= button_tag 'add to', type: 'button', class: "add-tag-btn" %>
          <div id="tag-list"></div>
          </div>
        </div>
      </div>
    </section>
    <section class="menu-tag-form">
      <h3>Tag details</h3>
      <table>
        <tbody>
          <%#Display only on the edit screen%>
          <% if truth %>
            <tr>
              <td><h4>Current tag list</h4></td>
              <td>
                <% menu_tags.each do |menu_tag| %>
                  <div class="menu-tag">
                    <%= Tag.find(menu_tag.tag_id).name %>
                    <%= link_to 'x', {controller: 'menu_tags', action: 'destroy', tag_id: menu_tag, menu_id: params[:id], restaurant_id: params[:restaurant_id]}, method: :delete %>
                  </div>
                <% end %>
              </td>
            </tr>
          <% end %>
          <tr>
            <td><h4>Add tag<br>(Recommended to select one or more)</h4></td>
            <td>
              <% tag_count = 0 %>
              <% tags.each do |tag| %>
                <%#Show 7 recommended tags%>
                <% if tag_count < 7 %>
                  <div class="check-box">
                    <% if menu_tags.exists?(tag_id: tag.id) %>
                      <%= check_box :tag_id, tag.id, checked: true %>
                      <%= label_tag :tag_id, "#{tag.name}"%>
                    <% else %>
                      <%= check_box :tag_id, tag.id %>
                      <%= label_tag :tag_id, "#{tag.name}"%>
                    <% end %>
                  </div>
                  <% tag_count += 1 %>
                <% else %>
                  <% break %>
                <% end %>
              <% end %>
            </td>
          </tr>
        </tbody>
      </table>
    </section>

    <section class="menu-form-area">
      <div class="content-form">
        <p><%= f.label :content, value: 'Contents' %></p>
        <%= f.text_area :content %>
      </div>
      <div class="cancel-form">
        <p><%= f.label :cancel, value: 'Cancellation Policy' %></p>
        <%= f.text_area :cancel %>
      </div>
    </section>

    <div class="submit"><%= f.button "#{submit}", onclick: 'submit();', type: 'button', class: 'btn' %></div>
  <% end %>

</div>

slim:_form.html.slim


.menu-form
  = form_with model: [restaurant, menu], url: path, local: true do |f|
    section.menu-status
      .menu-form1
h3 menu details
        table
          tbody
            tr
              td = f.label :title, value: 'Menu name'
              td = f.text_field :title
            tr
              td = f.label :regular_price, value: 'Regular price (excluding tax):'
              td
                = f.number_field :regular_price
                |Circle
            tr
              td = f.label :discount_price, value: 'Offer price (excluding tax):'
              td
                = f.number_field :discount_price
                |Circle
            tr
              td = f.label :reservation_method, value: 'Reservation method'
              td = f.select :reservation_method, Menu.reservation_methods.keys.map {|method| [method]}
            tr
              td = f.label :is_sale_frag, value: 'Sales status'
              td = f.select :is_sale_frag, [['Sale', true], ['Suspended', false]]
      .menu-form2
h3 menu image
        .menu-image
          = f.attachment_field :menu_image
          .image-preview
Add h4 tag (optional)
          = text_field_tag :tag_name
          = button_tag 'add to', type: 'button', class: "add-tag-btn"
          #tag-list
    section.menu-tag-form
h3 tag details
      table
        tbody
          /Display only on the edit screen
          - if truth
            tr
              td:h4 Current tag list
              td
                - menu_tags.each do |menu_tag|
                  .menu-tag
                    = Tag.find(menu_tag.tag_id).name
                    = link_to 'x', {controller: 'menu_tags', action: 'destroy', tag_id: menu_tag, menu_id: params[:id], restaurant_id: params[:restaurant_id]}, method: :delete
          tr
            td:Add h4 tag<br>(Recommended to select one or more)
            td
              - tag_count = 0
              - tags.each do |tag|
                /Show 7 recommended tags
                - if tag_count < 7
                  .check-box
                    - if menu_tags.exists?(tag_id: tag.id)
                      = check_box :tag_id, tag.id, checked: true
                      = label_tag :tag_id, "#{tag.name}"
                    - else
                      = check_box :tag_id, tag.id
                      = label_tag :tag_id, "#{tag.name}"
                  - tag_count += 1
                - else
                  - breeak
    section.menu-form-area
      .content-form
        p = f.label :content, value: 'Contents'
        = f.text_area :content
      .cancel-form
        p = f.label :cancel, value: 'Cancellation Policy'
        = f.text_area :cancel
    .submit= f.button "#{submit}", onclick: 'submit();', type: 'button', class: 'btn'

Summary / impression

All the above codes have been confirmed to work. Comparing the code amount of .erb and .slim, it is about 2/3. Indentation is very important, and if you make a mistake in indentation, you will usually get a syntax error. In that case, I commented out each block to check. With application.html.slim, comment out all the body, start only in the head, and if there is a syntax error in the head, use comment out again to isolate the problem. I hope it will be helpful for those who are thinking of rewriting to slim from now on.

If you have any questions, questions, differences in interpretation, or discomfort in the description method, please let us know in the comments.

Thank you for reading until the end.

Reference site

GitHub - slim Qiita --Quick Learning Template Slim (HTML Creation) Qiita-HTML template engine of Rails, basic notation of Slim Qiita-[Learn at explosive speed] From how to use slim with Rails to basic grammar Qiita --Slim Code Refactoring GitHub - matchi_ver.slim

Recommended Posts

Try changing the .erb file to .slim
Try changing to asynchronous processing via MQ without changing the code
Add Extended Attributes to the file
How to convert erb file to haml
[Java] How to use the File class
How to delete the wrong migration file
How to delete the migration file NO FILE
Double-click to open the jar file on Windows
[Spring Boot] How to refer to the property file
[Java] Try to solve the Fizz Buzz problem
Try to summarize the common layout with rails
[Java] How to extract the file name from the path
JavaFX-Specify the location of the CSS file relative to the fxml file
How to debug the generated jar file in Eclipse
Completely delete the migration file that you failed to delete
Command to try using Docker for the time being
Try to release gem
How to correctly check the local HTML file in the browser
Try switching from the RHEL environment to the Ubuntu environment Server installation
[Easy] How to automatically format Ruby erb file with vsCode
How to change the contents of the jar file without decompressing
How to change the file name with Xcode (Refactor Rename)