Plasticx Blog

Capable of being shaped or formed

Cookbook3, Ruby on Rails Tutorial

Posted by Mike 11/12/2006 at 01:59PM

The title to this blog entry is a bit misleading. This is really my notes on the implementing Curtis Hibbs’ “Rolling with Ruby on Rails” part 1 and part 2 . This is not a tutorial in and of itself but is a supplement to Curtis’s work. There must be ways to improve my code as well, so I look forward to learning from someone’s Cookbook4. My work can be found in the cookbook3.tar.bz2 file.

I’ll cover the following.

At the time of this writing I’m using Ruby 1.8.5 and Rails 1.1.6

Here are the three pages that helped me get started on Rails.

Generic mysql setup from the command line

Here are the basic mysql commands from the command line to create the development, test, and production users and databases. Edit to suit your setup.


mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON cookbook3_development.* TO ’cookbook3_dev’@’localhost’ IDENTIFIED BY ‘changeme’;
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON cookbook3_test.* TO ’cookbook3_test’@’localhost’ IDENTIFIED BY ‘changeme’; FLUSH PRIVILEGES;
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON cookbook3_production.* TO ’cookbook3_prod’@’localhost’ IDENTIFIED BY ‘changeme’;
mysql> FLUSH PRIVILEGES;
mysql> CREATE DATABASE cookbook3_development;
mysql> CREATE DATABASE cookbook3_test;
mysql> CREATE DATABASE cookbook3_production;

The corresponding entries in the config’s database yaml file (config/database.yml_) would then be:


development:
adapter: mysql
database: cookbook3_development
username: cookbook3
dev
password: changeme
host: localhost

And the CREATE statements for the recipes and categories tables are:


mysql> USE cookbook3_development;
mysql> CREATE TABLE `categories` (
`id` int(6) unsigned NOT NULL auto_increment,
`name` varchar(50) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
mysql> CREATE TABLE `recipes` (
`id` int(6) unsigned NOT NULL auto_increment,
`title` varchar(255) NOT NULL default ’’,
`description` varchar(255) default NULL,
`date` date default NULL,
`instructions` text,
`category_id` int(6) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

I also had to install the mysql gem for the mysql adapter to work. Make sure ruby dev for mkmf and libmysqlclient dev are installed on your system if you are running Linux/Unix/BSD

  1. gem install mysql

Rake commands for testing and stats

Be sure to know how to use your rake tool. The -T argument lists all your rake tasks available. “test” and “stats”, you want your stats Code to Test ratio to be close to 1.

$ rake -T
$ rake test
$ rake stats

Routing the cookbook to the root / of the web application

You can wire requests to the / root of the web server to the recipe controller, list action i.e. “/recipe/list”. In the file config/routes.rb define the default empty map.

map.connect '', :controller => 'recipe', :action => 'list'

Now requests to http://localhost:3000/ on the included server are treated the same as calling the controller and action directly http://localhost:3000/recipe/list

Valid XHTML 1.0 layout and nice CSS

In tutorial the standard layout for the application is placed a file called app/views/layouts/standard-layout.rhtml. The HTML needed to cleaned up and I have preference for XHTML 1.0 strict. I use a Firefox/Mozilla Add-on called Html Validator to help me validate the html that my code renders as I work along in a project. Here’s how I specified the doctype in the layout template:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Online Cookbook</title>
    <%= stylesheet_link_tag "main" %>
  </head>

Notice also that I use the stylesheet_link_tag method to link a cascading style sheet in the rails way. Passing that method “main” tells Rails that I have a CSS pages defined at public/stylesheets/main.css and it should be linked in. To create the main.css I just copied in the default CSS that is in-lined to rthml files created by the scaffold generator.

Controller actions as symbols verses strings

In the example string literals are used in the helper functions. For instance in the recipe controller’s delete function redirect_to invoked as redirect_to :action => 'list' . There isn’t any string overhead in Ruby when you use the symbols for your controllers methods in the helper functions. The rewrite of the parameters given redirect_to method in the delete action should be redirect_to :action => :list .

Use single quote strings where ever possible

There are many not needed double quoted strings used in the tutorial. Ruby will evaluate a double quoted string for replacement values. If you only need a literal use single quotes, they are not evaluated. For instance to define the string foo without evaluation: 'foo', to define the string foo that evaluates the value of the bar object with id use: "foo #{bar.id}" .

Use a render partial template for common forms

Use a partial template to render the common elements of the form used for new and update recipes. This is how its implemented in scaffold.

See app/views/recipe/_form.rhtml and app/views/recipe/new.rhtml and app/views/recipe/update.rhtml

ActiveRecord built-in validation

Use ActiveRecord’s validations to validate data input from the recipe forms. Error messages from ActiveRecord are displayed back to the user with ActionView::Helpers::ActiveRecordHelper’s error_messages_for and the flash array is used to display back success messages.

See app/models/recipe.rb

Adding click to sort on the Title column

The recipe results array’s sorting methods were used to implement click to sort on the Title column.

See app/controllers/recipe_controller.rb and app/views/recipe/list.rhtml

Adding view recipes by category

ActiveRecord find with conditions is used to limit the recipes by their category.

See app/controllers/recipe_controller.rb and app/views/recipe/list.rhtml

Geoffrey Grosenbach’s deprecated helper plugin

Another tool that helped me quit a bit is Geoffrey Grosenbach’s deprecated plugin

What you do is install it as a plugin then use its rake task to find all the deprecated code from the original tutorial. It finds all the deprecated rails code in the project, stuff like use of find_all instead of find(:all) on a ActiveRecord object.


ruby script/plugin install http://topfunky.net/svn/plugins/deprecated
rake deprecated

Functional and unit tests

The example functional and unit tests were pretty good. But I added functional tests to specifically test each action in the recipe controller. Specific unit tests to verify the attributes in the yaml fixtures was also added. I didn’t touch the category controller because its implementation is 100% scaffold. See A Guide to Testing the Rails for more information on good unit and functional tests.

Other Items Of Interest

SQLite – Its nice to know about the MySQL setup but its probably too heavy for a simple app like this. Consider using SQLite

Localization – Figure out a localization strategy to support multiple languages.

Resources

Posted in , , |

Trackbacks<

Use the following link to trackback from your own site:
http://plasti.cx/trackbacks?article_id=205


Web Statistics