When I wanted to start learning a language, my top options were Python and Ruby. After a long research I decided to start learning Ruby (on Rails after have been learned the basic of Ruby of course) for the simple reason that my co-founder is a Rails developer and that is an advantage when you want to ask questions.

Rails is actually a very good tool if you want to make a prototype of your idea faster and is easy to learn (the fundations I mean).

So, I’ll be doing a simple to-do web app with user authentication provided by Devise. Yes, hate me. And Bootstrap of course. All the stuff that I’m blogging are very basic and I’m doing it because is a good way to keep track of my skills. I’M NOT A DEVELOPER. For now this is my hobby and I love it. It helps me to keep my mind busy.

First things first. We have to create an app following this command:

workspace  rails new todoApp
      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

You’ll see a bunch of lines. It must takes a few minutes to end. After that switch to our app directory:

➜ cd todoApp

I’m going to create three models for this app: TodoList, Item and User.

TodoList: Name Item: Description, Status User: Mail, password

Ok, first I’m going to install simple_form. Go to the Gemfile and add:

gem 'simple_form'

Then run bundle install:

bundle install

And:

rails generate simple_form:install

Now we have to create the models. I’ll start with the TodoList model implementation:

rails g model TodoList name:string
rake db:migrate

Now that we have the model, lets go with the controller. Before to code anything, we have to think what we are going to need. In this particular case, we just be needing an index for all the todoList, a show to list the items in that to-do list and a new view to create a new one.

rails g controller TodoLists index show new

That creates a basic views and the controller with the actions.

Go to the routes.rb file and add:

resources :todo_lists

That generates the routes for TodoList.

I’ll start with the index action. Go to app/controllers/todo_lists_controller.rb. There you’ll find an index function already created. Should look like this:

class TodoListsController < ApplicationController
  
  def index
  end

  def new
  end

  def show
  end
end

On index, we just have to create a variable that holds all the todo lists:

def index
    @todoLists = TodoList.all
  end

Now that we have the index, we have to create the view (sort of, it’s already created by the rails g controller command)

Go to app/views/todo_lists/index.html.erb and there we are going make a home for all to-do lists. For now just type:

<h1>Todo Lists</h1>
<% @todoLists.each do |todoList| %>
  <p><%= todoList.name %></p>
<% end %>

We are basically iterating thru the @todoLists, that have all the to-do lists. In our case none. Lets fix that.

Go to console and type:

rails console

There type:

todolist = TodoList.new(name: “A list”)
todolist.save
todolist2 = TodoList.new(name: “Another list”)
todolist2.save
exit

Now start the server:

rails server

And go to localhost:3000/todo_lists/index

Actually go to routes.rb and type:

root 'todo_lists#index'

That set the root path to todo_lists/index. Ok, you must will see a list of the to-do lists that we just created through console.

image

Cool. Now we need to add to-dos through the app itself. Let’s go to the controller again and write:

def new
    @todoList = TodoList.new
end
def create
      @todoList = TodoList.create(todo_list_params)
            if @todoList.save
      flash[:success] = "To-do list created"
      redirect_to @todoList
    else
      flash[:error] = "Error creating to-do list"
      redirect_to new_todo_list_path
    end
 end

  private

  def todo_list_params
     params.require(:todo_list).permit(:name)
  end

At first I was little confused by new and create. Why two? they are the same? And the best answer is here: http://stackoverflow.com/questions/2472393/rails-new-vs-create

In simple words, new renders the form which allows us to create and save the records that create action handles.

Now we have to create to form. Go to the new view and type:

<%= simple_form_for @todoList do |t| %>
  <%= t.input :name %>
  <%= t.button :submit %>
<% end %>

It explains for itself. Simple_form allows us to create a form, passing @todoList (created in new in the controller, remember?). then when you hit submit, the view will call the create method, where the magic happens. go to http://localhost:3000/todos/new and create a new to-do list. A few if you want.

Let’s create a view for each to-do list. Go to todos_controller and add:

def show
  @todoList = TodoList.find(params[:id])
end

There we are looking for a @todoList to show on the view. Then go to the show.html.erb file and type:

<p><%= @todoList.name %></p>

We already have the views and controllers that allows us to create a to-do list, see it and see all of them in the index. Lets start creating the Item model.

Type in the console this and hit enter:

rails g model Item description:string status:boolean todo_list_id:integer

Now:

rake db:migrate

It’s time to create the associations. The logic says that we have a to-do list with many items in it, and an item belongs to a list, right? so in order to tell that to Rails, we have to go to the models and write some code (just a few, almost nothing, dont get bored).

todo_list.rb

class TodoList < ActiveRecord::Base
  has_many :items
end

item.rb

class Item < ActiveRecord::Base
  belongs_to :todo_list
end

That’s it. Now rails knows how our models are related (and before we added the todo_list_id to the Item model, remember?)

First we have to add the Item resource to the routes.rb file, write the following:

resources :todo_lists do
    resources :items
end

Now create the controller. We just need the create action:

rails g controller Items new

Go to the items_controller.rb and type:

class ItemsController < ApplicationController
  def new
    @todoList = TodoList.find(params[:todo_list_id])
    @item = @todoList.items.new
  end

  def create
    @todoList = TodoList.find(params[:todo_list_id])
    @item = @todoList.items.new(item_params)
    if @item.save
      flash[:success] = "Item created"
      redirect_to @todoList
    else
      flash[:error] = "Error creating item."
      redirect_to new_todo_list_item_path
    end
  end

  private

  def item_params
    params.require(:item).permit(:description, :status, :todo_list_id)
  end
end

The main difference here is we have to create an Item through the Todolist: item = @todoList.items.new(item_params). That because when we created the association between TodoList and Item, we gave TodoList the power to create Items.

Now go to app/views/items/new.html.erb view and type:

<%= simple_form_for [@todoList, @item] do |f| %>
  <%= f.input :description %>
  <%= f.input :status %>
  <%= f.button :submit %>
<% end %>

Then in app/views/todo_lists/index.html.erb view add:

<h1>Todo Lists</h1>
<% @todoLists.each do |todoList| %>
  <p><%= todoList.name %></p>
  <p><%= link_to "Go", todo_list_path(todoList) %></p>
<% end %>

<p><%= link_to "New to-do list", new_todo_list_path %></p>

In app/views/todo_lists/show.html.erb add:

<p><%= @todoList.name %></p>

<% @todoList.items.each do |item| %>
  <p><%= item.description %></p>
<% end %>

<p><%= link_to "Home", todo_lists_path %></p>
<p><%= link_to "Add Item", new_todo_list_item_path(@todoList) %></p>

And we are almost there. Now you can run your server and start creating items:

Go to a todo list and click Add Item. In the second part we are going to create the delete/edit functions, add bootstrap and Devise.

image