Ruby on Rails Project - To Do List #4

Well, I sure do let a lot of time go by between these posts. For a simple Rails project that will take around an hour or so to code, it's taken over a month to write the posts about it.

When I last left off we had a browser interface that would display a list of Projects, and if you clicked on one of those Projects you would be presented with a page displaying a list of Tasks associated with that Project. This is a great start to a Project Tracking application, but it's missing a big piece...an interface for allowing the user to enter the Projects and Tasks through the web browser. Everything we've added so far has happened from the command line. So, that is what I'll cover this time, adding a user interface for entering this information.

The page used for displaying the Projects is located at /app/views/projects/index.rhtml. The code is pretty simple


<h1>Projects</h1>
<ul>
    <% @projects.each do |project| %>
        <li><%= link_to project.name, :action => 'details', :id => project.id %></li>
    <% end %>
</ul>


We'll add the ability to add new Project to this same page, it will be at the top of the page. The existing projects will be listed below it.

First thing we'll do is update index.rhtml with the following code


<!-- Form for adding a new Project -->
<% form_tag :action => :new do %>
    Project Name: <%= text_field :project, :name %>
    <%= submit_tag 'Add new project' %>
<% end %>


This provides us with a text box and a button wrapped in a form that will submit to the 'new' method in the Project controller. The form should look like this if you view it in the browser at http://localhost:3000/projects/

project_from

Now we need to add the 'new' method to the Project Controller. This is located in /app/controller/projects_controller.rb. Add the following code


def new
  @newproject = params[:project]
  Project.new(@newproject).save
  redirect_to :action => :index
end


This code is pretty simple. When the user submits a new Project name, it comes over in the params object as a hash, with ':project' as the hash name, and ':name' as a key with the value the key corresponds to as the value they entered. Then we call the Save method and redirect back to index, which will redisplay the page with the new Project showing in the list.

This works great, you can add new Projects all day long, but there is an issue. We should have some sort of validation. We should validate that the user actually enters a value before clicking the button to create a project. We should also make sure the Project name they enter is unique. In most instances this would require a lot of coding on the developers part, but not in Rails. This is all taken care of. There are some pre-built validations, we'll use the validates_presence_of and validates_uniqueness_of validations, to check that the value has a length greater than 0 and also that the value is not already present in the database. We just need to add the validation calls to the Project model. The model is located at /app/models/project.rb, update it to look like this


class Project < ActiveRecord::Base
  has_many :tasks

  validates_presence_of :name
  validates_uniqueness_of :name
end


Now if you try to add a blank Project or one with a name already taken, nothing happens. Once we actually work on a layout to make this site presentable we can display error messages, but for the time being not having it save bad data is good enough.

Now we have to repeat the steps above to all the user the ability to add new Tasks to the project. Update the form that displays the tasks, which is located in /app/views/projects/details.rhtml. Add the following code after the <h1> tags


<% form_tag :action => :addtask, :id => @project.id do %>
    Task Name: <%= text_field :task, :name %><br />
    Due Date: <%= date_select('range', 'due_date', : order => [:month, :day, :year]) %><br />
    <%= submit_tag 'Add new task' %>
<% end %>


This gives us a form that looks like this

task_form

Next we add the 'addtask' method to the Project Controller, which will create a new instance of a Task with the information entered by the user, find the Project that the task is going to be associated with, and adds the task to the tasks array of the Project, then it saves the project.


def addtask
  #create task
  @task = Task.new(params[:task])
  @task.is_complete = false

  #add to project
  @project = Project.find_by_id(params[:id])
  @project.tasks << @task
  @project.save

  redirect_to :action => 'details', :id => params[:id]
end


Add the following to the Task model, and you are done.


validates_presence_of :name


We'll allow duplicate task names, but the task does need a name entered.

That's all for this time. Next time we will allow updating and deleting of tasks. Also, we'll need to show overdue tasks.
|