Featured image of post Rails Cheatsheet

Rails Cheatsheet

Rails Tips and Tricks

Installation

First thing first, install Ruby in your machine (see Ruby Cheatsheet). And check whether there is any rails installation already exist by running this

1
gem search '^rails$' --local

If rails doesn’t exist, install rails by using

1
gem install rails -v '6.1.6' -V --no-document

You can install another rails version available on remote server. Check the other versions with

1
gem search '^rails$' --all

Projects

To generate new project we can use this command

1
rails new appname

Rails generate new app with sqlite as default database. If we want to have project with postgresql database, use rails new appname -d postgresql or rails new appname -d mysql. These are requiered Gem pg or mysql2 for mysql database.

You also can generate specific rails version that have already installed before

1
rails _5.2.4.1_ new app_name

Here I write some sample project apps to make us familiar with the syntax

TODOO Application

Generate Scaffolding

Here we’ll learn about how to generate simple CRUD application using rails g, using console rails c, create and migrate database using rails db:create and rails db:migrate and play with simple route and form validation.

  1. Generate new project rails new todoo
  2. Move to the project folder cd todoo and run local server rails s. Check the web browser http://localhost:3000/ and you must see rails-welcome screen. If you get an error, it might be database error. Let’s create database in the next step.
  3. If you have not yet created the project database, you can create using rails command rails db:create
  4. Generate your first resource called todo rails g scaffold Todo title task:text
  5. Migrate the resources to your database table using rails db:migrate
  6. You also can rollback your migration by using rails db:rollback. Don’t forget to migrate again.
  7. Rails automatically creates routing for ‘Todo’ resource. To see what routes available run rails routes
  8. Routing investigation also can be done by console. Run rails c and type Rails.application.routes.recognize_path("/todos") then you will get this
1
2
irb(main):001:0> Rails.application.routes.recognize_path("/todos")
=> {:controller=>"todos", :action=>"index"}
  1. The result above means that path /todos are handled by TodosController in file app/controllers/todos_controller.rb with index action. In the file you can see there are seven action available, i.e. index, show, new, edit, create, update, and destroy
  2. Still in the console, you also can check home route by using Rails.application.routes.recognize_path("/")
  3. Now try to edit file ‘config/routes.rb’, we add a line to handle homepage with ’todos#index’ controller
1
2
3
4
5
Rails.application.routes.draw do
  root to: "todos#index"
  resources :todos
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
  1. Try to re-run again, open web browser and access http://localhost:3000/. Now instead you have rails welcome screen, you get index todo page.
  2. Play around with simple todo app from web browser. Try add some data.
    simple todo app
  3. From console rails c, you can also view the record using command Todo.all for all record, Todo.first for first record, or for more specific result, use Todo.last.task for the task field in the last record.
  4. You also can create new record from console. i.e. Todo.create(title:"Elixir",task:"Learn Elixir...") or update the existing record, i.e. Todo.first.update(title:"Clean")
  5. How if there is anyone put title only without provide task input. Is it still valid?. Then you can check it from the console. Initialize c variable c = Todo.new(title:"c") then run c.valid?. Then it should print true
  6. To avoid the problem, we should put validation in app/models/todo.rb
1
2
3
4
class Todo < ApplicationRecord
  validates :title, presence: true
  validates :task, presence: true
end
  1. Reload the console using reload! and try again as step 16 state. Now you should get false

Layout

  1. Adding Bootstrap into the Gemfile
1
2
3
4
gem 'bootstrap', '~> 5.1.3'
gem 'bootstrap-icons', '~> 1.0', '>= 1.0.12'
gem 'bootstrap-icons-helper'
...
  1. Running bundle install to download the new dependencies bundle install
  2. Rename app/assets/stylesheets/application.css to app/assets/stylesheets/application.scss
  3. Then add the lines in the file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@import "bootstrap";

main.container {
    width: auto;
    max-width: 680px;
    padding: 0 15px;
    padding-bottom: 60px;
 }

 footer {
    position: fixed;
    bottom: 0;
    width: 100%;
    height: 60px;
    line-height: 60px;
    background-color: #f5f5f5;
    text-align: center;
 }

 .media p {
    font-size: 16px;
 }

 a:hover {
    background: #f5f5f5;
 }
  1. In app/views/layouts/application.html.erb add these lines to create footer and wrap yield which will render a specific view template.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
  ...

  <body>
    <main role="main" class="container">
      <%= yield %>
    </main>

    <footer class="footer">
      <div class="container">
        <span class="text-muted">
          Todoo by Ananto
        </span>
      </div>
    </footer>
  </body>
</html>
  1. Put our own style to file app/views/todos/index.html.erb
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<p id="notice"><%= notice %></p>
<br/>
  <% @todos.each do |todo| %>
      <div class="d-flex">
        <div class="flex-shrink-0">
          <img src="<%= gravatarized_url(todo.title) %>" class="align-self-start mr-3">
        </div>
        <div class="flex-grow-1 ms-3">
          <h5><%= todo.title %></h5>
          <%= todo.task %>
        </div>
        <div class="flex-shrink-0">
          <span>
            <%= link_to todo,  class: 'btn btn-primary btn-sm' do %>
               <%= bootstrap_icon "eye", width: 16, height: 16, fill: "white" %>
            <% end %>
          </span>
          <span>
            <%= link_to edit_todo_path(todo),  class: 'btn btn-primary btn-sm' do %>
              <%= bootstrap_icon "pencil-square", width: 16, height: 16, fill: "white" %>
            <% end %>
          </span>
          <span>
            <%= link_to todo, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-primary btn-sm' do %>
               <%= bootstrap_icon "trash", width: 16, height: 16, fill: "white" %>
            <% end %>
          </span>
        </div>
      </div>
    <br/>
  <% end %>
<%= link_to 'New Todo', new_todo_path %>
  1. Define gravatarized_url inside TodosHelper in file app/helpers/todos_helper.rb
1
2
3
4
5
6
module TodosHelper
    def gravatarized_url(title)
        hash = Digest::MD5.hexdigest(title)
        "https://www.gravatar.com/avatar/#{hash}?d=wavatar"
    end
end
  1. Check your page now. It’s cool. But for better user experience, let’s render the form on the index page.
    Add the following code into todo/index.html.erb
1
2
3
4
5
6
7
8
<p id="notice"><%= notice %></p>

<%= render("form", todo: Todo.new) %>

<br/>
  <% @todos.each  do |todo| %>
      <div class="d-flex">
...
  1. Replace the content of todos/_form.html.erb with the following codes:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div class="card">
  <div class="card-body">
    <h5 class="card-title">Create A Task!</h5>

    <%= form_with(model: todo) do |form| %>
      <% if todo.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(todo.errors.count, "error") %> prohibited this todo from being saved:</h2>
          <ul>
            <% todo.errors.each do |error| %>
              <li><%= error.full_message %></li>
            <% end %>
          </ul>
        </div>
      <% end %>
      <div class="form-group mb-3">
        <%= form.text_field :title, placeholder: "Title", class: "form-control" %>
      </div>

      <div class="form-group mb-3">
         <%= form.text_area :task, placeholder: "Task", class: "form-control" %>
      </div>

      <div class="actions">
        <%= form.submit "Add!", class: "btn btn-outline-primary w-100" %>
      </div>
    <% end %>
  </div>
</div>
  1. We also want to improve user experience after he add task. Instead redirect to other page, we want to user stay on the index page and see the task he recently added on the top list.
    edit TodosController#create
1
2
3
4
5
6
def create
  @todo = Todo.new(todo_params)

  respond_to do |format|
    if @todo.save
      format.html { redirect_to root_path, notice: "Todo was successfully created." }

also change TodosController#index

1
2
3
def index
  @todos = Todo.all.order(created_at: :desc)
end
  1. Ta Da.. Here the final view of our Todoo application
    Todoo

Another Application


References:

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy