Welcome! If you’re here, you’d like to learn to make Rails web apps. I’d love to take you through making the quintessential “To-do” list.

Ingredients

  • 1 computer
  • 1 Terminal or Command Line Prompt
  • 1 installation of Ruby and(on) Rails
  • 1 text editor
  • 1 happy coder

Recipe

Installing Rails

Getting Rails on your computer is nice and simple, but a bit different depending on what Operating System you’re running:

Windows

It used to be fairly difficult to get a Ruby environment, let alone a Rails one running. Fortunately, the Rails Installer project makes it as simple as downloading the installer for your Windows version and running the installation program. If you’re wondering what version to install, I’d go with the one with the latest Ruby version (2.1).

OS X (10.9 Mavericks or newer)

Mac users have the convenience of having Ruby installed into their computers. Having said that, I’d recommend installing Ruby Version Manager, or RVM. What rvm offers is full control over what version of ruby you’re running on your Mac, as well as a simple way to install gems (more on that later).

To install rvm, open your Terminal (Applications -> Utilities) and type in the following:

\curl -sSL https://get.rvm.io | bash -s stable --ruby

This will install rvm on your Mac, along with the latest version of ruby.

The next step will require you to close your Terminal window, then re-open it. Why? Because this will let rvm take over the latest version of ruby. Next, install rails with the following Terminal command:

gem install rails

Once again, we’ll get into what a gem is later on.

Linux

Installing rails on your Linux machine requires a different command depending on your distribution.

Ubuntu

bash < <(curl -sL https://raw.github.com/railsgirls/installation-scripts/master/rails-install-ubuntu.sh)

Fedora

bash < <(curl -sL https://raw.github.com/railsgirls/installation-scripts/master/rails-install-fedora.sh)

Verifying Your Installation

To double check that everything is running smoothly, you can open up your Terminal or command line and type in the following:

rails -v

What this should do is print in the screen what version of rails you’re running. If this gives you an error, it’d be a good idea to go back to the last step and make sure you’ve installed everything correctly. In my case, it returns the following:

Rails 4.2.0

If all else fails, I’d suggest making a free account on Cloud9. This is an online platform that takes care of setting up rails, and is like having your own separate computer on the browser (note: Cloud9 provides a nice button for starting up the server as opposed to starting it from the command line.)

A place to write our code

Text editors are utilities for us to write our code and save it for computer to use when running our program or app. For the purposes of this tutorial, unless you already have one that you know and love, I’d suggest using Atom. It’s open source, and made with a lot of love from the folks at GitHub.

Let’s get this party started!

First, we’ll begin by creating a new rails project.

Open up your terminal. It should open to the home folder on your computer. On a Mac or Linux box, you’d see the following:

cosima:~ ramonh$ 

Let’s go through what we see here:

  • cosima is my computer (huge Orphan Black fan here)
  • ~ is the name of the folder we’re currently located in within the Terminal. What is ~, you ask? That’s our home folder. This is a common standard across Unix or Linux OS’
  • ramonh, perhaps self-explanatorily, is the username.
  • $ after this, your command will be entered

Create your rails project

After the rails gem was installed, the rails command line tool became available to us. We can use it to create a new rails project:

rails new todo-list

What follows next could take a while. Your output should look something like the following:

      create
      create  README.rdoc
      create  Rakefile
      create  config.ru
      create  .gitignore
      create  Gemfile
      create  app
      create  app/assets/javascripts/application.js
      create  app/assets/stylesheets/application.css
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/views/layouts/application.html.erb
      create  app/assets/images/.keep
      create  app/mailers/.keep
      create  app/models/.keep
      create  app/controllers/concerns/.keep
      create  app/models/concerns/.keep
      create  bin
      create  bin/bundle
      create  bin/rails
      create  bin/rake
      create  bin/setup
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/secrets.yml
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/assets.rb
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/cookies_serializer.rb
      create  config/initializers/filter_parameter_logging.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/session_store.rb
      create  config/initializers/wrap_parameters.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  lib
      create  lib/tasks
      create  lib/tasks/.keep
      create  lib/assets
      create  lib/assets/.keep
      create  log
      create  log/.keep
      create  public
Fetching gem metadata from https://rubygems.org/............
Fetching version metadata from https://rubygems.org/...
Fetching dependency metadata from https://rubygems.org/..
Resolving dependencies...
Using rake 10.4.2
Using i18n 0.7.0
Using json 1.8.3
Using minitest 5.7.0
Using thread_safe 0.3.5
Using tzinfo 1.2.2
Using activesupport 4.2.1
Using builder 3.2.2
Using erubis 2.7.0
Using mini_portile 0.6.2
Using nokogiri 1.6.6.2
Using rails-deprecated_sanitizer 1.0.3
Using rails-dom-testing 1.0.6
Using loofah 2.0.2
Using rails-html-sanitizer 1.0.2
Using actionview 4.2.1
Using rack 1.6.1
Using rack-test 0.6.3
Using actionpack 4.2.1
Installing globalid 0.3.5
Installing activejob 4.2.1
Installing mime-types 2.6.1
Installing mail 2.6.3
Installing actionmailer 4.2.1
Using activemodel 4.2.1
Using arel 6.0.0
Using activerecord 4.2.1
Installing debug_inspector 0.0.2
Installing binding_of_caller 0.7.2
Using bundler 1.9.2
Using columnize 0.9.0
Using byebug 5.0.0
Installing coffee-script-source 1.9.1.1
Installing execjs 2.5.2
Installing coffee-script 2.4.1
Using thor 0.19.1
Using railties 4.2.1
Installing coffee-rails 4.1.0
Using multi_json 1.11.0
Installing jbuilder 2.2.16
Installing jquery-rails 4.0.3
Installing sprockets 3.2.0
Installing sprockets-rails 2.3.1
Installing rails 4.2.1
Using rdoc 4.2.0
Installing sass 3.4.14
Installing tilt 1.4.1
Installing sass-rails 5.0.3
Installing sdoc 0.4.1
Installing spring 1.3.6
Using sqlite3 1.3.10
Installing turbolinks 2.5.3
Installing uglifier 2.7.1
Installing web-console 2.1.2
Bundle complete! 12 Gemfile dependencies, 54 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
         run  bundle exec spring binstub --all
* bin/rake: spring inserted
* bin/rails: spring inserted

What happened here might look like a lot, and believe me, it is! Put simply, rails generated most of the files we’ll need to run our web app, as well as installed all the gems we’ll need. Which begs the question…

What exactly is a gem?

Excellent question! I like to think of a gem as exactly the same as a framework or library. That is, a collection of pre-written code available for us to use. If we weren’t using rails, for example, we’d have to directly write every interaction we’d have with the database in SQL, or each HTTP request out fully. The purpose of gems is to save us the effort of doing so. That doesn’t mean, of course, that knowing how these gems work is not important. Au contraire.

It’s alive! IT’S ALIVE!

Let’s move into the folder of our new rails app in the Terminal:

cd todo-list

You’ll see the folder name todo-list in our prompt. Great! We can now start up our server:

rails server

What happens next looks a little odd at first. What’s all this output? Why can’t I put in any more commands?

=> Booting WEBrick
=> Rails 4.2.1 application starting in development on https://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
[2015-06-10 14:44:46] INFO  WEBrick 1.3.1
[2015-06-10 14:44:46] INFO  ruby 2.2.1 (2015-02-26) [x86_64-darwin14]
[2015-06-10 14:44:46] INFO  WEBrick::HTTPServer#start: pid=23528 port=3000

Do not fear! This is a good sign that you now have a healthy server running. The reason you can’t enter any more commands is because the server for your rails app is running there. You can even see on the second line how to check it out. Let’s open https://localhost:3000 and see what we’ve got!

Rails

… wat. What is this?

No worries! This is a friendly pre-generated webpage to let us know that everything is running smoothly and offer tips on where to go next.

If you want to shut down your server, rails already told you how to do so on the fourth line of our helpful output. Simply hit Ctrl-C (doesn’t need to be capital C).

Generate a scaffold for our todos

… Generate a what, now? We’ll need to take a step back.

Ever heard of Model View Controller, or MVC?

MVC

Image courtesy of Wikipedia

Though it looks complicated, the idea behind this structure of software is quite simple:

  • A model stores the data needed for the app. It sends this data for the view to display to the user.
  • A view is a visual representation of the data shown to the user
  • By interacting with the view, the user sends commands to the controller, which in turn manipulates the data stored in the model

Back to scaffolding

Scaffolding is an automated tool provided by rails that generates the models, the views, and the controllers for a specific thing you want to control with your web app.

For our app, we can use the scaffold to generate our todo objects (note: it is vital that we stick to the naming of ‘todo’). That is, we will use the scaffold generator to make our model, view, and controller for the todos.

What will todos consist of?

Let’s think about what we’ll need to manipulate in a todo item. We’ll need a title for it, so we can know what it is we want to do. It would also be good to have a description, so that the user could put in more text that potentially wouldn’t make sense to be in the title. Finally, and perhaps most obviously, we’d need to know whether the todo has been completed or not.

So let’s make that scaffold for it

Hold on there, let’s look at the actual command first. Instead of you copy pasting it, I’ll show you an example:

rails generate scaffold user username:string email:string password:string date_of_birth:date height:float bio:text

Whoa, what is this? It’s quite simple, really. With this command, we’re generating a scaffold for a user object. rails generate scaffold tells rails that what comes next, that is, the user will be the name of the thing we’ll be working with. After that come the fields. Our user will have six fields: username, email, password, date_of_birth, height and bio.

You might be wondering what the parts after the :’s are. Quite simply, the computer would need to know what type of data we’re working with for each field. So let’s see what each of these are:

  • string - A sequence, or ‘string’ of characters.
  • date - Quite simply, a date
  • float - A floating-point number. That is, a number with decimal points
  • text - A body of text

Hold on - text and string sound like the exact same thing, don’t they? Well, no. Simply put, string stores less data. That is, you allocate less space to store your shorter text. Normally, email addresses and usernames are not very long. However, when it comes to things like bio’s or description’s (hint), then you might need more than 500 characters.

Other types include:

  • integer - A whole number
  • time - A time of day!
  • binary - This one is a little more complex. binary is used for storing data that isn’t as simple as text or numbers. This can be things like music data, photo data, and others.
  • boolean - Ever heard of these before? A boolean is a type that can have two values: true or false.

I have a challenge for you, dear reader. You must now generate your rails scaffold for the todo. Remember, it will have three fields: title, description, and completed. Can you come up with the data types needed for it? One hint: A todo can either be completed or not. ;)

What’s all this output?!

If you’ve generated your todo scaffold correctly, you should see something like this:

      invoke  active_record
      create    db/migrate/20150611104736_create_todos.rb
      create    app/models/todo.rb
      invoke    test_unit
      create      test/models/todo_test.rb
      create      test/fixtures/todos.yml
      invoke  resource_route
       route    resources :todos
      invoke  scaffold_controller
      create    app/controllers/todos_controller.rb
      invoke    erb
      create      app/views/todos
      create      app/views/todos/index.html.erb
      create      app/views/todos/edit.html.erb
      create      app/views/todos/show.html.erb
      create      app/views/todos/new.html.erb
      create      app/views/todos/_form.html.erb
      invoke    test_unit
      create      test/controllers/todos_controller_test.rb
      invoke    helper
      create      app/helpers/todos_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/todos/index.json.jbuilder
      create      app/views/todos/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/todos.coffee
      invoke    scss
      create      app/assets/stylesheets/todos.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss

Do not be alarmed! I wasn’t kidding when I said that rails would generate a ton of stuff for us. If you look keenly, you’ll see that we’ve had our model, our views, and our controllers generated for us, as well as other things, like css and helper files.

The one we want to look at right now, however, is the file on the second line: the migration file.

In fact, let’s open it! You can find it within your project folder, and in db/migrate. It should look something like this:

class CreateTodos < ActiveRecord::Migration
  def change
    create_table :todos do |t|
      t.string :title
      t.text :description
      t.boolean :completed

      t.timestamps null: false
    end
  end
end

This looks weird, but it’s quite simple. This file will be called and run when we want to set up our database. Databases are typically stored in tables of data. What we are doing here is creating a new table called todos, where each row will have three columns: title, description and completed. That is, each todo item will have the three fields, just like we specified in our scaffolding. Neat, huh? If you want to know more about migrations, check out the rails documentation section on migrations. It’s quite handy.

To actually set up our database, we need to tell it to be migrated. rails provides a bunch of pre-written commands in something called a Rakefile, that we can invoke by typing rake into our Terminal, followed by the command we want to run. (If you’re curious, run rake -T to see what commands are available to you in the Rakefile).

rake db:migrate

You should see the following output:

== 20150611104736 CreateTodos: migrating ======================================
-- create_table(:todos)
   -> 0.0009s
== 20150611104736 CreateTodos: migrated (0.0010s) =============================

Looks simple, and that’s cause it is! All this did was run that migration file we check out earlier and add the todos table to the database.

Guess what? A huge bulk of the work is already done.

Don’t believe me? Start up your rails server. Remember how to? Then head over to the website. Again, I’m hoping you remember how to do so. :)

Er.

Rails

Well, this is awkward.

Hehehe don’t worry, it’s normal.

Even though we generated a scaffold for the todo’s, the root page is still the “Welcome aboard” one. We’ll fix this soon enough, but first, let’s check out our list of todo’s.

For our convenience, amongst other things, when we generated the scaffold, rails also generated the URL (the address) for our todo objects. You just need to enter the localhost address like before, but afterwards append /todos. In my case, as shown below, it’s simply https://localhost:3000:

Rails

As expected, the list seems empty and we can create new todo’s.

Creating ‘todo’ items is fairly straightforward, and I don’t think requires a screenshot.

Once we’ve entered it and returned to our list page, we can see our lovely new todo.

Rails

Huh. Well, it works, but the true or false entry is kind of bland. For this, I think it would be cool to use icons.

Integrating icons

I’d suggest the handy-dandy Font Awesome. But before we do that, it’s important to first understand…

How our web app is displayed

As you might’ve guessed, if we want to look at and/or change how our web app is displayed, you’re gonna need to look in the app/views directory, files shown below:

Rails

All your pages run the application.html.erb

If you’ve worked with html files before, you might be a little confused. What is this erb extension?

erb, you might have guessed (I sure didn’t) stands for Embedded RuBy. This basically allows you to enter ruby code tags into your html. No worries, we’ll get into that in a sec.

So open up that application.html.erb file and take a look at what’s inside:

<!DOCTYPE html>
<html>
<head>
  <title>TodoList</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>

As you can see, it’s nice and short.

Those of you familiar with html could be thrown off with the tags that look like <%. This is where erb comes in. It allows you to insert ruby code to be run. The output of that ruby command is converted to html.

For example, you’ll see that the erb calls for stylesheets and javascripts are converted to html tags (if you’ve never seen html before, it might be a good idea to go through a tutorial. If you have time, I’d recommend the CodeAcademy one.)

But what about that yield call?

Well that’s where it gets interesting. When you open a page in your web app, it will display everything here, and then yield the main part to another html.erb file, which contains the meat of that page. For instance, when opening the todos/index.html.erb file, the yield would convert to the following:

<p id="notice"><%= notice %></p>

<h1>Listing Todos</h1>

<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Description</th>
      <th>Completed</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @todos.each do |todo| %>
      <tr>
        <td><%= todo.title %></td>
        <td><%= todo.description %></td>
        <td><%= todo.completed %></td>
        <td><%= link_to 'Show', todo %></td>
        <td><%= link_to 'Edit', edit_todo_path(todo) %></td>
        <td><%= link_to 'Destroy', todo, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Todo', new_todo_path %>

I hope that makes sense! While we’re here, let’s take a look at how each todo is displayed.

The first few lines should coincide with what we normally see in a webpage. We have our header, table with headers, and then comes the table body.

…And then comes the ruby. Don’t worry, it’s quite simple, really.

What we’re doing here is grabbing the list of @todos, and going through .each of them. It shall be referred to as a single todo. We then create a table row where we display its title, description, whether it was completed, and a link to show it individually, edit it, or to delete, or destroy the todo. The code will then be run for each todo, and that’s how we display each row for each todo. Simple!

Here, we can edit our completed field to display a nice icon.

To do so, let’s finally integrate that FontAwesome icon set.

Integrating Font Awesome into our app

Font Awesome’s Get Started page shows that it’s really simple to add the icon set to your webpage. You need to add the stylesheet:

If you’re familiar with html, you’d know that we need to add the link to our head tag. In order to make it available to all pages, we need to do so in…… Which html.erb file again? ;)

Using them icons

So now that we’ve integrated Font Awesome, we can go ahead and use it!

Open up the todos/index.html.erb and change the the following line:

<td><%= todo.completed %></td>

…to the following:

<% if todo.completed %>
<% else %>
<% end %>

Finished, right?

Wrong. You, dear reader, have been trolled!

The html tag for creating a checkmark icon, for example, is <span class='fa fa-check></span>. Can you deduce where to place it? This would be a great icon for showing that a todo has been completed.

Once you’ve done that, create the html tag for the incomplete icon. For a list of icons, check out Font Awesome’s list.

Once you’ve made the changes, refresh that page!

Rails

Forgive the pun, but I’d say it looks awesome.

One final tweak

I’ll show you one more tweak for today. I don’t know about you, but I wasn’t happy with the fact that going to the root of the website takes me to the “Welcome aboard” page. I want my todos to be there.

Introducing routes

routes tell rails which webpage to show you when you enter a certain address or url. This is set up automatically when you create a rails app and is tweaked automatically when you generate pages or scaffolds. Let’s take a looksie in config/routes.rb:

Rails.application.routes.draw do
  resources :todos
  # The priority is based upon order of creation: first created -> highest priority.
  # See how all your routes lay out with "rake routes".

  # You can have the root of your site routed with "root"
  # root 'welcome#index'

  # Example of regular route:
  #   get 'products/:id' => 'catalog#view'

  # Example of named route that can be invoked with purchase_url(id: product.id)
  #   get 'products/:id/purchase' => 'catalog#purchase', as: :purchase

  # Example resource route (maps HTTP verbs to controller actions automatically):
  #   resources :products

  # Example resource route with options:
  #   resources :products do
  #     member do
  #       get 'short'
  #       post 'toggle'
  #     end
  #
  #     collection do
  #       get 'sold'
  #     end
  #   end

  # Example resource route with sub-resources:
  #   resources :products do
  #     resources :comments, :sales
  #     resource :seller
  #   end

  # Example resource route with more complex sub-resources:
  #   resources :products do
  #     resources :comments
  #     resources :sales do
  #       get 'recent', on: :collection
  #     end
  #   end

  # Example resource route with concerns:
  #   concern :toggleable do
  #     post 'toggle'
  #   end
  #   resources :posts, concerns: :toggleable
  #   resources :photos, concerns: :toggleable

  # Example resource route within a namespace:
  #   namespace :admin do
  #     # Directs /admin/products/* to Admin::ProductsController
  #     # (app/controllers/admin/products_controller.rb)
  #     resources :products
  #   end
end

The parts with the # are comments, and usually ignored. These are notes left for you, the happy coder! In the second line, you’ll notice the resources: todos line. This basically tells rails to treat your todo pages the way it does, with listing, showing, editing, and creating new todos.

Let’s tell the routes to change the root page to be our todos page. After the first line, add the following as a new line:

root 'todos#index'

A word to the wise: You’ll probably need to stop the rails server and start it up again.

Load the root page again. Check it out! Now you’re on your todo list, as intended.

So what exactly did we add here? Simply put, we’re telling rails that the root page is mapped to the todo’s index action, which you may recognize as the index.html.erb view file from earlier.

Not bad, huh?

You’ve just made an app in rails. Take a moment to pat yourself in the back.

This should give you a jumpstart into the world of web app development with rails. As you can probably tell, we’re barely scratching the surface. If you’re itching to do more practising, try doing things like changing the show, edit and destroy links into icons, or try adding a field to your todo model.

Ideally, if guides could go on forever, I’d show you how to take the style of the website to the next level using Twitter Bootstrap, but that shall be for another time.

Toodles!

Buy me a coffee