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:
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:
Then run bundle install:
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:
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:
todolist = TodoList.new(name: “A list”) todolist.save todolist2 = TodoList.new(name: “Another list”) todolist2.save exit
Now start the server:
And go to localhost:3000/todo_lists/index
Actually go to routes.rb and type:
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.
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
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).
class TodoList < ActiveRecord::Base has_many :items end
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.