This course is for people who have either never written a line of code in their life, or are new to Ruby on Rails. In this chapter I’m going to show you how to set up a workspace on Cloud9 (a browser-based development environment) and build a to-do list application.

Ruby is a programming language, and rails is the name of a web application framework written in ruby. There are so many good reasons to start developing with Ruby on Rails as your first framework: it’s widely used and well-documented, it’s simple to get your head around, and it enables you to develop complicated large-scale web apps quickly by doing a lot of the work for you.

I was in your position not so long ago, and Ruby on Rails opened up a whole new world of opportunities to me. Let’s begin.

Cloud9

Using Cloud9, we can get straight into development without worrying about the pain of installing software. Navigate to https://c9.io and sign up for a free account. Once you’re logged in select “Create A New Workspace” and enter the options as follows:

Cloud9 Workspace Options

Once that’s finished initialising, you should be greeted by a screen like this:

Cloud9 Workspace Greeting

There’s 3 panes here: a navigator to the left, a text editor in the upper right, and a terminal in the lower right. On the left, you can see we already have a rails project set up. Cloud9 has performed one step for us: normally we would need to run the command rails new <appname> to generate all this boilerplate code.  What we effectively have here is an app named rails_workspace. Now, follow the instructions on the README that’s open in the text editor by default, and you should be able to navigate to the default ruby on rails landing page which looks like this:

Ruby On Rails Landing Page

So without doing any work, Cloud9 has gotten a default Rails application going for us.

Linux

Before we dive into actually writing some code, I want to talk more about the command line in your Cloud9 interface. In the bottom right panel, close the Immediate tab and switch to the bash tab (you can leave the rails server running). It’ll look like this:

Empty Shell

What you’re actually looking at is the screen of virtual computer running Ubuntu Server. Ubuntu (a flavour of Linux) is an operating system just like Windows or OSX, but in this form it doesn’t have any windows or buttons; you only interact with it through your keyboard. Linux still has files and directories, and your terminal session is always sitting inside a directory; ~/workspace shown in blue above is the current directory which can be changed using the following commands:

Command Function
ls Lists the files and folders in the current directory
pwd Prints the current directory
cd folder Changes into the directory named folder if it exists inside the current directory

There are also special symbols in our terminal:

Symbols  Meaning
/  The root directory. All other directories are contained inside the root directory and the root directory has no parent directories.
~  Home directory. Usually located at /home/username (the username is ubuntu in this Cloud9 virtual machine)
..  Parent folder (cd .. moves up a folder)
.  Current folder (cd . changes nothing)

Running these commands literally just means typing them into the terminal and pressing enter. You won’t really need to use any of these commands with Cloud9 set up like it is. We’re mostly just going to be running rails commands.

Ruby

We now have an environment in which we can run ruby. In your Cloud9 terminal, type irb (for interactive ruby) and press enter. You can now start executing ruby code (you type exit to quit). If this is your first time learning a programming language, I implore you to go and learn a bit of ruby on your own at this point. Definitely read some of this brief guide to ruby if-statements. There are plenty of excellent and short guides that will give you the basic level of knowledge required to read and write ruby code. Otherwise, feel free to just copy and paste my code (even if you know a bit of ruby, a lot of the rails syntax will still be confusing at first).

In terms of resources I recommend, have a look at this article and figure out how to add and subtract numbers, and so on.  It’s a good idea to know what stringsvariables, collections, symbolsiterators and hashes are in ruby. You’ll have a better time if you learn that stuff first.

Rails

One of the many great things about rails are generators. Rails will save us a lot of time by generating files full of code for us. We could easily write them ourselves (which we’ll do later), but not in this short chapter. There are three core types of files that every rails app has: models, views, and controllers. This pattern of separating code into three categories is called MVC (model, view, controller) architecture.

The logic behind MVC architecture is this: any incoming requests are handled by a controller, which gets information from the model, then the controller returns actual webpages based on views. A model describes a type of object. For example a to-do is a type of object, so we’ll have a Todo model. Views are in charge of rendering the actual web page that users see.

Rails can generate all the controllers, models, and views we need in just one command. Run the following:

rails generate scaffold Todo name:string

rails generate scaffold is first passed a model name (conventionally written in CamelCase), then the properties of that model in the form  property_name:type property_name:type .... What’s going on here is pretty self-explanatory: we’re generating a model called Todo with one property called name; name is a string (which just means text).

Rails will spit out a bunch of text telling you about all the files it generated. The files we’re interested in are:

TODO MODEL:
app/models/todo.rb

VIEWS:
app/views/todos/index.html.erb
app/views/todos/edit.html.erb
app/views/todos/show.html.erb
app/views/todos/new.html.erb
app/views/todos/_form.html.erb

TODOS CONTROLLER:
app/controllers/todos_controller.rb

DATABASE MIGRATION (begins with a timestamp):
db/migrate/xxxxxx_create_todos.rb

As you can see, rails has generated view files for indexing, editing, showing and creating to-dos. In fact, we already have a functioning to-do management application. Before we can use it, however, we need to run one command to finish creating the database:

rake db:migrate

Before, when we ran rails generate scaffold rails told you it created the file db/migrate/xxxxxx_create_todos.rb. rake db:migrate checks for new files like this, and it uses the information in them to update the structure of the database. After running rake db:migrate you’ll be able to find the following file:  db/development.sqlite3. This is where all of our to-dos are actually stored; a local sqlite3 database.

Restart your server (navigate to the server terminal and stop/start), access it in your browser, and navigate to /todos.

Listing Todos

How cool’s that?Create some to-dos and get familiar with the app. You’ve made your first app, but it’s ugly and you have no idea how it works. Let’s change that.

Routes

Open up config/routes.rb and delete all the lines starting with hashes – these are just comments that do nothing but explain things. The file should look like this:

Rails.application.routes.draw do
  resources :todos
end

config/routes.rb is a configuration file containing ruby code (as indicated by the .rb) which tells rails which controllers particular URL extensions (like /todos) are supposed to go to. The resources keyword here is actually a cryptic shortcut, so I want you to delete it and replace it with the following:

Rails.application.routes.draw do
 get 'todos', to: 'todos#index'
 get 'todos/new', to: 'todos#new', as: :new_todo
 post 'todos', to: 'todos#create'
 get 'todos/:id', to: 'todos#show', as: :todo
 get 'todos/:id/edit', to: 'todos#edit', as: :edit_todo
 patch 'todos/:id', to: 'todos#update'
 delete 'todos/:id', to: 'todos#destroy'
end

Now it should be slightly more clear what’s happening. Each one of these routes represents an action such as indexing to-dos or creating a new one. Look at line 2. Here, this configuration file is telling our app to direct requests for the URL /todos to ‘todos#index’ which is short hand for the index method of the todos controller.

HTTP

The protocol by which webpages are served to users is called the Hypertext Transfer Protocol (HTTP), and there are various types of HTTP requests a user can make. GET requests are made when a user simply enters a URL into their browser or clicks a link. POST/PATCH requests on the other hand are usually performed through a form submission, and carry the data from the form with them.

Here’s a depiction of roughly what happens when a user navigates to a particular URL, and then submits a form on that page.

User navigates to the page with the form on it:

Post Flow

User submits the form:

Create Todo

This will make more sense as we continue. Let’s have a look at the logic inside our controller’s actions.

Controllers

If you open up /app/controllers/todos_controller.rb you’ll see all the actions we’ve been referring to in config/routes.rb, but they don’t seem to contain very much. For example, show is empty. The reason these empty actions are still rendering pages is because rails knows where to look by default. Under the hood, show could look like this and it would do the same thing:

### app/controllers/todos_controller.rb

...
# GET /todos/1
# GET /todos/1.json
def show
  respond_to do |format|
    format.html { render 'todos/show.html' }
    format.json { render 'todos/show.json.jbuilder' }
  end
end
...

The respond_to method’s syntax here is a bit confusing, but basically it means that if the request was for a HTML file (GET /todos/1), then render show.html, and if the request was for a JSON file (GET /todos/1.json) then return the information in JSON format. JSON stands for Javascript Object Notation and it’s a convenient way to communicate the properties of an object to, say, a mobile app. The path specified in the render method is relative to app/views. So in the code above, show is rendering the file app/views/todos/show.html, and that’s the file you see in your browser when you click “show” on a to-do!

The reason the show method knows which item to show is because of the line:  before_action :set_todo, only: [:show, :edit, :update, :destroy] (line 2). This is telling rails: before running the show, edit, update, or destroy actions, call the method set_todo, which is defined at the bottom of the file:

### app/controllers/todos_controller.rb

...
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_todo
      @todo = Todo.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def todo_params
      params.require(:todo).permit(:name)
    end
end

Looking inside the set_todo method here, you can see rails is using the find method of our Todo model to get a to-do object with a specific ID from the database. It stores this object in a variable called @todo. The @ here makes @todo an instance variable. Normally variables only exist where they’re defined, but instance variables become available anywhere in a class (we can use it in the show method even though it was defined in the set_todo method). @todo, when defined, will also be available in our views. We’ll see @todo referenced inside our views to access its name. Before we look at show.html, a side note on the params variable:

Params

params is a variable that is available in controllers. It’s a hash, which means it holds key-value pairs which are defined like this: params = { 'id' : 23 }, and you access them with square brackets like this: id = params['id'] (read more about hashes). In ruby, params['id'] is synonymous with  params[:id], that is the string (designated by quotes) 'id' can be used interchangeably with the symbol :id  in this context (read more about symbols, the words preceded by a colon).

The id entry in our params hash actually comes from our route, which looks like this:

### config/routes.rb

Rails.application.routes.draw do
  ...
  get 'todos/:id', to: 'todos#show', as: :todo
  ...
end

Rails is doing a bit of magic and taking the number that follows todos/ and putting it in our params hash as :id.

Views

We’re going to have a look at our views and then change the structure of our app to make it more user friendly. First, check out show.html.erb:

### app/views/todos/show.html.erb

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

<p>
  <strong>Name:</strong>
  <%= @todo.name %>
</p>

<%= link_to 'Edit', edit_todo_path(@todo) %> |
<%= link_to 'Back', todos_path %>

This file is comprised of HTML with some ruby mixed in.

HTML

Fact about the internet: all webpages are comprised of HTML, which stands for Hypertext Markup Language. Learn everything you need to know about HTML in about two minutes here. When you write HTML, you’re mostly just writing opening and closing tags that communicate page structure such as <p>This is a paragraph!</p> and <h1>This is a heading!</h1>.  HTML tags can also have attributes. For example, a link usually has a “href” attribute (Hypertext Reference) and looks like this:

<a href="http://google.com">Visit google.com!</a>

The href attribute sets the URL that the link points to.

 

To see the HTML that a webpage is made of, right click anywhere on the page (other than a link) and select the option resembling “view page source”.

show.html.erb contains HTML and embedded ruby — that’s the stuff in the <% xxx %> tags. Whenever we want to use ruby methods and functions in our view we need to use these tags. <%= xxx %> tags embed the output of embedded Ruby code into the HTML, whereas <% xxx %> is for hidden logic. You can see in show.html.erb that we’re using our @todo instance variable that we were talking about before in todos_controller.rb. 

Still in app/views/todos/show.html.erb, the line: <%= link_to 'Back', todos_path %> is an example of a Ruby helper method. todos_path is a variable defined by rails based on our routes, and the link_to helper method is going to generate a HTML link for us which looks like this:

<a href="/todos">Back</a>

Now have a look at app/views/layouts/application.html.erb. Rails actually renders all of our HTML views inside this parent template. This is a default behaviour you can override, but you usually don’t want to because it helps us avoid rewriting generic HTML/ruby code that we need in every view. Our views are embedded in this file wherever there’s the line: <%= yield %>. Feel free to change the site title inside the <title> tags.

Styling

To make our app pretty, we’re going to use a gem called bootstrap-sass. Gems are convenient packages of code we can use in our application, and bootstrap is a library of styles convenient for quickly developing good looking apps. Gems are managed by the Gemfile, found in the root of our application. Add the bootstrap-sass gem by adding it to the end of your Gemfile:

### Gemfile

...
gem 'bootstrap-sass'

In your Cloud9 terminal, run the command bundle install to install this gem. Now add the following lines to the top of app/assets/stylesheets/todos.scss (feel free to delete the comments found there by default):

### app/assets/stylesheets/todos.scss

@import "bootstrap-sprockets";
@import "bootstrap";
CSS

All webpages use a language called Cascading Stylesheets (CSS) to describe the appearance of the page (learn more about CSS). Rails, by default, allows you to create styles in a similar language called Sassy CSS (SASS) which is compiled into CSS and is a lot more efficient to write (learn about SASS).

Although you can put CSS right in your HTML files with <style> tags, it’s a best practise to write CSS in a seperate file to your HTML (we’re already doing this when we put styles in app/assets/stylesheets/. These are linked to our HTML document by a ruby helper method in app/views/layouts/application.html.erb<%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>.

CSS looks like this:

.item {
  color: red;
}

This CSS would select all the HTML elements with the class of “item” and make their text colour red. An HTML element’s class is specified in the class attribute, and and element can have more than one class:

<p class="item other-class">Hello world!</p>

We need to delete some annoying styles generated as a part of the rails generate scaffold command. Delete the file app/assets/stylesheets/scaffolds.scss.

Controllers

We’re going to delete every view aside from the index view, and create/delete to-dos from there. First, update our routes file:

### config/routes.rb

Rails.application.routes.draw do
  root 'todos#index'
  get 'todos', to: 'todos#index'
  post 'todos', to: 'todos#create'
  delete 'todos/:id', to: 'todos#destroy', as: :todo #as: :todo lets us use todo_path variable
end

We only need these routes because we’re going to list all of our todos on the same page as the form that creates them. We’ve also defined a root route so we no longer need to navigate to /todos; the root domain will take us to the index now. Now, to todos_controller.rb. I’m going to delete all the irrelevant actions and any code that renders JSON files. I’m also going to replace any references to actions that don’t exist anymore (like redirects to the new method). The file now looks like this:

class TodosController < ApplicationController
  before_action :set_todo, only: [:destroy]

  def index
    @todos = Todo.all
  end

  def create
    @todo = Todo.new(todo_params)
    @todo.save
    redirect_to todos_url
  end

  def destroy
    @todo.destroy
    redirect_to todos_url
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_todo
      @todo = Todo.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def todo_params
      params.require(:todo).permit(:name)
    end
end

Views

Now we refactor our views. Delete all the files in todos/views aside from index.html.erb and change the contents of index.html.erb to this:

### app/views/todos/index.html.erb

<h1 align="center">My To-do List</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3 col-sm-12">
    <div class="panel panel-default">
      <div class="panel-heading">My To-Do List</div>
      <table class="table">
        <thead> 
          <tr> 
            <th>To-Do</th> <th>Actions</th>
          </tr> 
        </thead>
        <tbody>
          <% @todos.each do |todo| %>
          <tr>
            <td scope="row"><%= todo.name %></td>
            <td scope="row"><%= link_to 'Delete', todo, method: :delete, data: { confirm: 'Are you sure?' } %></td>
          </tr>
          <% end %>
        </tbody>
      </table>
    </div>
    
    <%= form_for(@todo) do |f| %>
      <%= f.text_field :name, class: "form-control" %>

      <div style="margin-top: 1em;">
        <%= f.submit "Create", class: "btn btn-primary" %>
      </div>
    <% end %>
  </div>
</div>

All of the HTML classes used here are bootstrap classes, so these HTML elements will have bootstrap styling. Learn about bootstrap components here. We also use some table HTML elements, and a form generated by the rails form_for helper. These are all things you can Google and learn more about. We’re almost done, but we reference an instance variable in our index view that we haven’t defined in our index action. The form references @todo in the line: <%= form_for(@todo) do |f| %>, and right now @todo is undefined. To fix this, change our index action in the todos controller to look like this:

### app/controllers/todos_controller.rb

...
def index
  @todos = Todo.all
  @todo = Todo.new
end
...

And now, after restarting your server (because we installed a new gem), it’s all ready to go.

Navigate to your app and you should see the something that looks like this:

To-Do List App

And that’s it for this chapter. In the next chapter, we’ll begin making our real social app and deploy it to a live server.