Rails Scaffolding

While you're developing Rails applications, especially those which are mainly providing you with a simple interface to data in a database, it can often be useful to use the scaffold method.
Scaffolding provides more than cheap demo thrills. Here are some benefits:
  • You can quickly get code in front of your users for feedback.
  • You are motivated by faster success.
  • You can learn how Rails works by looking at generated code.
  • You can use the scaffolding as a foundation to jumpstarts your development.

Scaffolding Example:

To understand scaffolding lets create a database called cookbook and a table called recipes:

Creating an Empty Rails Web Application:

Open a command window and navigate to where you want to create this cookbookweb application. I used c:\ruby. So run the following command to create complete directory structure.
C:\ruby> rails cookbook

Setting up the Database:

Here is the way to create database:
mysql> create database cookbook;
Query OK, 1 row affected (0.01 sec)

mysql> grant all privileges on cookbook.*
to 'root'@'localhost' identified by 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
To tell Rails how to find the database, edit the configuration file c:\ruby\cookbook\config\database.yml and change the database name to cookbook. Leave the password empty. When you finish, it should look something like
development:
  adapter: mysql
  database: cookbook
  username: root
  password: [password]
  host: localhost
test:
  adapter: mysql
  database: cookbook
  username: root
  password: [password]
  host: localhost
production:
  adapter: mysql
  database: cookbook
  username: root
  password: [password]
  host: localhost
Rails lets you run in development mode, test mode, or production mode, using different databases. This application uses the same database for each.

Creating the database tables:

We will use following table for our practical purpose. So create recipes table from sql prompt as follows:
mysql> USE cookbook;
Changed database
mysql> CREATE TABLE recipes (
    -> id INT(11) NOT NULL AUTO_INCREMENT,
    -> title VARCHAR(40),
    -> instructions VARCHAR(255),
    -> PRIMARY KEY (id));
Query OK, 0 rows affected (0.06 Sec)
NOTE: If you wish you can use Rails Migrations to create and maintain tables.

Creating Model:

First, create a Recipe model class that will hold data from the recipes table in the database. Use the following command inside cookbook directory.
C:\ruby\cookbook > ruby script\generate model Recipe
Notice that you are capitalizing Recipe and using the singular form. This is a Rails paradigm that you should follow each time you create a model.
This will create a file named app/models/recipe.rb containing a skeleton definition for the Recipe class.

Creating Controller:

Now we have to create a recipe controller with actions to manipulate the recipes in the database via the standard CRUD operations: create, read, update, and delete.
C:\ruby\cookbook > ruby script\generate controller Recipe
Notice that you are capitalizing Recipe and using the singular form. This is a Rails paradigm that you should follow each time you create a controller.
This will create a file named app/controllers/recipe_controller.rb containing a skeleton definition for the RecipeController class. Edit this file and add the linescaffold:recipe as shown
class RecipeController < ApplicationController
   scaffold:recipe
end
This single line of code will bring the database table to life. This will provide with a simple interface to your data, and ways of:
  • Creating new entries
  • Editing current entries
  • Viewing current entries
  • Destroying current entries
When creating or editing an entry, scaffold will do all the hard work of form generation and handling for you, and will even provide clever form generation, supporting the following types of inputs:
  • Simple text strings
  • Textareas (or large blocks of text)
  • Date selectors
  • Datetime selectors
Now go into cookbook directory and run Web Server using following command:
C:\ruby\cookbook> ruby script/server
Now open a browser and navigate to http://127.0.0.1:3000/recipe/new, This will provide you a screen to create new entries in recipes table. A screen shot is shown below:
Create Recipe
Once you press Create button to create anew recipe, your record is added into recipes table and it shows following result:
Create Recipe
You can see option to edit, show and destroy the records. So play around these options.
You can also list down all the recipes available in the recipes table using URL http://127.0.0.1:3000/recipe/list

Enhancing the Model:

Rails gives you a lot of error handling for free. To understand this, add some validation rules to the empty recipe model:
Modify app/models/recipe.rb as follows and then test your application:
class Recipe < ActiveRecord::Base
   validates_length_of :title, :within => 1..20
   validates_uniqueness_of :title, :message => "already exists"
end
These entries will give automatic checking that:
  • validates_length_of: the field is not blank and not too long
  • validates_uniqueness_of: duplicate values are trapped. I don't like the default Rails error message - so I have given my custom message.

The Generated Scaffold Code:

With the scaffold action, Rails generates all the code it needs dynamically. By running scaffold as a script, we can get all the code written to disk where we can investigate it and then start tailoring it to our requirements.
So now let's start once again to generate Scaffold code manually by using scaffold helper script:
C:\ruby\cookbook> ruby script/generate scaffold recipe
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/recipes
      exists  app/views/layouts/
      exists  test/functional/
  dependency  model
      exists    app/models/
      exists    test/unit/
      exists    test/fixtures/
   identical    app/models/recipe.rb
   identical    test/unit/recipe_test.rb
   identical    test/fixtures/recipes.yml
      create  app/views/recipes/_form.rhtml
      create  app/views/recipes/list.rhtml
      create  app/views/recipes/show.rhtml
      create  app/views/recipes/new.rhtml
      create  app/views/recipes/edit.rhtml
      create  app/controllers/recipes_controller.rb
      create  test/functional/recipes_controller_test.rb
      create  app/helpers/recipes_helper.rb
      create  app/views/layouts/recipes.rhtml
      create  public/stylesheets/scaffold.css
C:\ruby\cookbook>

The Controller:

Let's look at the code behind the controller.This all code is generated by scaffoldgenerator. So if you will open app/controllers/recipes_controller.rb then you will find something as follows:
class RecipesController > ApplicationController
  def index
    list
    render :action => 'list'
  end

  verify :method => :post, :only => [ :destroy, :create, :update ],
         :redirect_to => { :action => :list }

  def list
    @recipe_pages, @recipes = paginate :recipes, :per_page => 10
  end

  def show
    @recipe = Recipe.find(params[:id])
  end

  def new
    @recipe = Recipe.new
  end

  def create
    @recipe = Recipe.new(params[:recipe])
    if @recipe.save
      flash[:notice] = 'Recipe was successfully created.'
      redirect_to :action => 'list'
    else
      render :action => 'new'
    end
  end

  def edit
    @recipe = Recipe.find(params[:id])
  end

  def update
    @recipe = Recipe.find(params[:id])
    if @recipe.update_attributes(params[:recipe])
      flash[:notice] = 'Recipe was successfully updated.'
      redirect_to :action => 'show', :id => @recipe
    else
      render :action => 'edit'
    end
  end

  def destroy
    Recipe.find(params[:id]).destroy
    redirect_to :action => 'list'
  end
end
When the user of a Rails application selects an action . e.g. "Show" - the controller will execute any code in the appropriate section - "def show" - and then by default will render a template of the same name - "show.rthml". This default behavior can be overwritten:
The controller uses ActiveRecord methods such as find, find_all, new, save, update_attributes, and destroy to move data to and from the database tables. Note that you do not have to write any SQL statements, rails will take care of it automatically.

The Views:

All the views and corresponding all the controller methods are created by scaffoldcommand and they are available in app/views/recipes directory.

How Scaffolding is Different?

If you have gone through previous chapters then you must have seen that we had created methods to list, show, delete and create data etc but scaffolding does that job automatically.

No comments:

Post a Comment

Site Search