Ruby on Rails Project - To Do List #3
Jan 17 2008 10:53 PM Filed in: Ruby
In step
two of my PC Task project I created my
models for Projects and Tasks. In step three I
will move on to the Controllers and Views.
We'll start off with the Projects Controller. Just like we used a script to generate our Model, we can do the same thing with our Controller. The syntax for creating a Controller is
$ ruby script/generate controller controller_name
So, to create our Projects Controller type the following
$ ruby script/generate controller Projects index
You should receive something similar to the following
exists app/controllers/
exists app/helpers/
create app/views/projects
exists test/functional/
create app/controllers/projects_controller.rb
create test/functional/projects_controller_test.rb
create app/helpers/projects_helpers.rb
create app/views/projects/index.rhtml
So, you'll probably notice I added an extra argument on to the end of that command, 'index'. The default name for the file that is accessed when a user visits your site is the index page, so adding this extra argument just created the index.rhtml page for us. If you leave it off, you can always create it later yourself.
Before I move on, I never did define what Model, View, Controller really meant. Here's a couple quick definitions.
Model - handles data and business logic
Controller - handles user interface and application logic
View - handles GUI objects and presentation logic
In a web application the chain of events is
a. Web browser sends a request for a page to the controller.
b. Controller gets the data it needs from the model.
c. Controller renders the page then sends it to the view.
d. View displays the page in the browser.
OK, if you were to start the application, using the following command
$ ruby script/server
and you open a browser and navigate to http://localhost:3000/projects, you should see a page that has the following displayed
Now, we need to decide what we want to display in the View, so we can code for this in the Controller. I think at the moment we can just display a list of all the Projects.
Now, before I go any further I want to do a quick introduction to a feature of Rails called Scaffolding. Scaffolding is a tool that can quickly create a view for you that you can use to interact with your model. The view that's created lists all the data in the table and creates an interface for performing your CRUD operations. Scaffolding used to be the selling point of Rails, back when it was the new kid on the block. It's a fun little feature, but I think most developers forgo it for creating their own Controller and View. Scaffolding is very easy. Open the projects controller ($ mate app/controller/projects_controller.rb) and modify the file to look like the following
class ProjectsController < ApplicationController
scaffold :project
end
Now, save the file and refresh the page in your browser that points to http://localhost:3000/projects. Your web page should now look like this
I had created a Test Project in step #2, so it is showing here. As you can see, it has all of the CRUD operations on the screen. This is a cool feature, something I would love sometimes at work in .NET WinForms (I think something similar to this is available in ASP.NET 2008, which is a pretty good clone of Rails, way to innovate again Microsoft), but it's not the route we will take. Instead we will go "our own route".
Modify the Controller file to look like the following
class ProjectsController < ApplicationController
def index
@projects = Project.find(:all)
end
end
Here we define an index action and the find(:all) returns all records in the Projects table. If you refresh the page in your browser you are back to this page
We haven't defined any code in our view (index.rhtml), so nothing is displayed yet. We now need to update the View to show a list of Projects. Open the index.rhtml file and update it like so
<h1>Projects</h1>
<ul>
<% @projects.each do |project| %>
<li><%= link_to project.name, :action => 'details', :id => project.id %></li>
<% end %>
</ul>
What all is this doing? @project is an instance variable, he was defined in the Controller. The line with @projects.each do |project| is basically looping through the items stored in @projects, which is the result of the find(:all) command, and storing the current item in project, which is then used when writing out the list. The link_to command is an HTML helper that wraps the item in anchor tags. If you view the page in the browser now you should see the following
Not as cool and exciting as what was created by Scaffolding, but it's a start. If you click on the link you will receive an error. This is because we defined an action called 'details' that we haven't defined yet. Let's do that now. Add the following to the Projects Controller.
def details
@project = Project.find_by_id(params[:id])
@tasks = @project.tasks
end
This uses the project.id that is passed as id in the parameters and gets the tasks related to that project. Now we need to create a details.rhtml page. Create one in the same directory as index.rhtml and add the following code
<h1><%= @project.name %></h1>
<ol>
<% @tasks.each do |task| %>
<li><%= task.name %> <%= task.due_date %> <%= task.is_complete %></li>
<% end %>
</ol>
Now, if you click on the link on index.html you should see a page similar to the following
Not the prettiest page in the world, but it will do for now.
We now have a Controller that will gather the information about the Projects and the associated Tasks, and will display that information in our index and details View.
In step 4 I will add more of the CRUD functionality.
We'll start off with the Projects Controller. Just like we used a script to generate our Model, we can do the same thing with our Controller. The syntax for creating a Controller is
$ ruby script/generate controller controller_name
So, to create our Projects Controller type the following
$ ruby script/generate controller Projects index
You should receive something similar to the following
exists app/controllers/
exists app/helpers/
create app/views/projects
exists test/functional/
create app/controllers/projects_controller.rb
create test/functional/projects_controller_test.rb
create app/helpers/projects_helpers.rb
create app/views/projects/index.rhtml
So, you'll probably notice I added an extra argument on to the end of that command, 'index'. The default name for the file that is accessed when a user visits your site is the index page, so adding this extra argument just created the index.rhtml page for us. If you leave it off, you can always create it later yourself.
Before I move on, I never did define what Model, View, Controller really meant. Here's a couple quick definitions.
Model - handles data and business logic
Controller - handles user interface and application logic
View - handles GUI objects and presentation logic
In a web application the chain of events is
a. Web browser sends a request for a page to the controller.
b. Controller gets the data it needs from the model.
c. Controller renders the page then sends it to the view.
d. View displays the page in the browser.
OK, if you were to start the application, using the following command
$ ruby script/server
and you open a browser and navigate to http://localhost:3000/projects, you should see a page that has the following displayed
Now, we need to decide what we want to display in the View, so we can code for this in the Controller. I think at the moment we can just display a list of all the Projects.
Now, before I go any further I want to do a quick introduction to a feature of Rails called Scaffolding. Scaffolding is a tool that can quickly create a view for you that you can use to interact with your model. The view that's created lists all the data in the table and creates an interface for performing your CRUD operations. Scaffolding used to be the selling point of Rails, back when it was the new kid on the block. It's a fun little feature, but I think most developers forgo it for creating their own Controller and View. Scaffolding is very easy. Open the projects controller ($ mate app/controller/projects_controller.rb) and modify the file to look like the following
class ProjectsController < ApplicationController
scaffold :project
end
Now, save the file and refresh the page in your browser that points to http://localhost:3000/projects. Your web page should now look like this
I had created a Test Project in step #2, so it is showing here. As you can see, it has all of the CRUD operations on the screen. This is a cool feature, something I would love sometimes at work in .NET WinForms (I think something similar to this is available in ASP.NET 2008, which is a pretty good clone of Rails, way to innovate again Microsoft), but it's not the route we will take. Instead we will go "our own route".
Modify the Controller file to look like the following
class ProjectsController < ApplicationController
def index
@projects = Project.find(:all)
end
end
Here we define an index action and the find(:all) returns all records in the Projects table. If you refresh the page in your browser you are back to this page
We haven't defined any code in our view (index.rhtml), so nothing is displayed yet. We now need to update the View to show a list of Projects. Open the index.rhtml file and update it like so
<h1>Projects</h1>
<ul>
<% @projects.each do |project| %>
<li><%= link_to project.name, :action => 'details', :id => project.id %></li>
<% end %>
</ul>
What all is this doing? @project is an instance variable, he was defined in the Controller. The line with @projects.each do |project| is basically looping through the items stored in @projects, which is the result of the find(:all) command, and storing the current item in project, which is then used when writing out the list. The link_to command is an HTML helper that wraps the item in anchor tags. If you view the page in the browser now you should see the following
Not as cool and exciting as what was created by Scaffolding, but it's a start. If you click on the link you will receive an error. This is because we defined an action called 'details' that we haven't defined yet. Let's do that now. Add the following to the Projects Controller.
def details
@project = Project.find_by_id(params[:id])
@tasks = @project.tasks
end
This uses the project.id that is passed as id in the parameters and gets the tasks related to that project. Now we need to create a details.rhtml page. Create one in the same directory as index.rhtml and add the following code
<h1><%= @project.name %></h1>
<ol>
<% @tasks.each do |task| %>
<li><%= task.name %> <%= task.due_date %> <%= task.is_complete %></li>
<% end %>
</ol>
Now, if you click on the link on index.html you should see a page similar to the following
Not the prettiest page in the world, but it will do for now.
We now have a Controller that will gather the information about the Projects and the associated Tasks, and will display that information in our index and details View.
In step 4 I will add more of the CRUD functionality.
|