Rails Basics (using NetBeans 6.8)

Sang Shin, Michèle Garoche, www.javapassion.com/rubyonrails

   

Rails is a web application and persistence framework that includes everything needed to create database-backed web applications according to the Model-View-Control design pattern. This pattern splits the view (also called the presentation) into "dumb" templates that are primarily responsible for inserting pre-built data in between HTML tags. The model contains the "smart" domain objects (such as Account, Product, Person, Post) that holds all the business logic and knows how to persist themselves to a database. The controller handles the incoming requests (such as Save New Account, Update Product, Show Post) by manipulating the model and directing data to the view.

In this lab, you are going to build several simple Rails applications step by step.  Even though they are very simple applications, you will get an exposure to the whole development cycle of building a Rails application including the creation of the model, a controller, and a view.  


Expected duration: 100 minutes (excluding homework)



Software Needed

Before you begin, you need to install the JDK and NetBeans IDE software on your computer as described in  here.


OS platforms you can use

Change Log


Things to be done (by the authors of this lab)


Lab Exercises


Exercise 0: Start MySQL database server


In this exercise, you are going to start MySQL database server (of course assuming you have installed the MySQL database server).  For more detailed information on MySQL, please refer to MySQL 5.1 Reference Manual.   For more information on how to use MySQL with NetBeans, please see Connecting to a MySQL Database (using NetBeans) tutorial.

You can start the MySQL server in a different way from the way described below. For example, for Windows platform, it could be started as a Windows service.
  1. Configure MySQL database server with NetBeans
  2. Start MySQL database server

(0.1) Configure MySQL database server with NetBeans


1. Install MySQL database server (if you have not done so yet.)  Set the password of the root user to null since most sample applications that are provided set with that configuration. (Of course, you do not want to do this in production environment.)

2. Register MySQL Server to NetBeans.



MySQL Tip: Here is how you can change your MySQL password at the command line. Note that the MySQL Server should be started beforehand.  If the <new-password> is null, you should type " (a single double-quote) as <new-password>.

C:\mysql-5.1.32-win32\bin>mysqladmin -u root -p password <new-password>
Enter password: ************  (Type in old password)

3. Configure MySQL Server.  (This is optional.  This could be useful when you want to start MySQL from NetBeans IDE. If you are going to start MySQL using different means - for example, as a Services under Windows platform -, there is no need to configure this.)




(0.2) Start MySQL database server


1. Right click MySQL Server at localhost:3306[root] (disconnected) and select Start.  (If you have not started MySQL server yet).


Figure-1.11: Start MySQL database server


Mac OS X User Tip: You cannot start the MySQL server from NetBeans, you may start is either as daemon, or via a shell script containing :

#!/bin/sh
sudo echo
sudo mysql_safe &

Nevertheless, it may be useful to enter the paths to the mysql tools, so that you get access to the mysqladmin tool. 

To stop the MySQL Server, the arguments to mysqladmin are: -u root shutdown

2. Test if the MySQL database server is running.


                                                                                                                 

Exercise 1: Build and run "helloworld" Rails application


In this exercise, you use the Ruby on Rails support in the NetBeans IDE to create and run a simple helloworld web application.  Even though this is a very simple application, you will get an exposure to the the whole development cycle of building a Rails application including the creation of a model, a controller, and a view.

Key learning points: 
Tasks to be performed:
  1. Create a Rails project
  2. Create database
  3. Create a Model
  4. Create database table through migration
  5. Create a Controller
  6. Create a View
  7. Set URL Routing (and delete index.html)
  8. Build and run the application


(1.1) Create Ruby on Rails NetBeans project


1. Create Ruby on Rails NetBeans project.

Figure-1.11: Create a new NetBeans project

Figure-1.12: Create Ruby on Rails Application project

2. Give project a name.

Figure-1.13: Give a name to a project

3. Observe that the IDE creates various directories.  Note that the Figure-1.14 below shows the logical view of the directories.


Figure-1.14: Observe the directories that are created by the IDE (in logical view)

4. If you want to see the actual directories that have been created, select Files tab window as shown in Figure-1.15 below


Figure-1.15: Actual directories that have been created

<Study point: Directory structure of a Rails application>

When you ask NetBeans to create a Rails project  - internally NetBeans uses the rails' helper script -, it creates the entire development directory structure for your application. Rails knows where to find things it needs within this structure, so you don't have to tell it explicitly.

The directory structure of a Rails application looks as following.  Please note that NetBeans uses logical names to reflect these directories. For example, the Controllers node represents app/controllers directory while Models node represents app/models and Views node represents app/views.  If you click Files view of the project, you will see the directories mentioned below.

app
Holds all the code that's specific to this particular application.
app/controllers
Holds controllers that should be named like weblogs_controller.rb for automated URL mapping.
All controllers should descend from ApplicationController which itself descends from ActionController::Base.
app/models
Holds models that should be named like post.rb.
Most models will descend from ActiveRecord::Base.
app/views
Holds the template files for the view that should be named like weblogs/index.html.erb for the WeblogsController#index action. All views use eRuby syntax.
app/views/layouts
Holds the template files for layouts to be used with views.
This models the common header/footer method of wrapping views. In your views, define a layout using the layout :default and create a file named default.html.erb. Inside default.html.erb, call <% yield %> to render the view using this layout.
app/helpers
Holds view helpers that should be named like weblogs_helper.rb. These are generated for you automatically when using script/generate for controllers. Helpers can be used to wrap functionality for your views into methods.
config
Configuration files for the Rails environment, the routing map, the database, and other dependencies.
db
Contains the database schema in schema.rb. 
db/migrate
Contains all the sequence of Migrations for your schema.
doc
This directory is where your application documentation will be stored when generated using rake doc:app
lib
Application specific libraries. Basically, any kind of custom code that doesn't belong under controllers, models, or helpers. This directory is in the load path.
public
The directory available for the web server.
Contains subdirectories for images, stylesheets, and javascripts.
Also contains the dispatchers and the default HTML files.
This should be set as the DOCUMENT_ROOT of your web server.
script
Helper scripts for automation and generation.
test
Unit and functional tests along with fixtures. When using the script/generate scripts, template test files will be generated for you and placed in this directory.
vendor
External libraries that the application depends on. Also includes the plugins subdirectory.
If the app has frozen rails, those gems also go here, under vendor/rails/.
This directory is in the load path.
Physical directories that are created for the Ruby on Rails project

<Study point: Configuration/database.yml>

Rails provides the concept of "environments" - development, test, production - and assumes you will be using a different database for a different environment. Therefore each environment has its own database connection settings as shown below.

development:
  adapter: jdbcmysql
  encoding: utf8
  reconnect: false
  database: helloworld_development
  pool: 5
  username: root
  password:
  host: localhost

# Warning: The database defined as 'test' will be erased and
# re-generated from your development database when you run 'rake'.
# Do not set this db to the same as development or production.
test:
  adapter: jdbcmysql
  encoding: utf8
  reconnect: false
  database: helloworld_test
  pool: 5
  username: root
  password:
  host: localhost

production:
  adapter: jdbcmysql
  encoding: utf8
  reconnect: false
  database: helloworld_production
  pool: 5
  username: root
  password:
  host: localhost
Configuration/database.yml

5. If you are using non-null password for your MySQL database, add the password to the database.yml.

development:
  adapter: jdbcmysql
  encoding: utf8
  reconnect: false
  database: helloworld_development
  pool: 5
  username: root
  password: <my_mysql_password>
  host: localhost

# Warning: The database defined as 'test' will be erased and
# re-generated from your development database when you run 'rake'.
# Do not set this db to the same as development or production.
test:
  adapter: jdbcmysql
  encoding: utf8
  reconnect: false
  database: helloworld_test
  pool: 5
  username: root
  password: <my_mysql_password>
  host: localhost

production:
  adapter: jdbcmysql
  encoding: utf8
  reconnect: false
  database: helloworld_production
  pool: 5
  username: root
  password: <my_mysql_password>
  host: localhost


                                                                                                                   return to top of exercise

(1.2) Create Database


1. Create database manaully with MySQL Server Create Database....




2. Verify that the helloworld_development database is created using NetBeans.

Figure-1.30: jdbc connection to helloworld_development database

Figure-1.29: New database connection is created


  Trouble-shooting: If you don't see MySQL Server at localhost:3306[root] under Databases node, create a connection manually.

Figure-1.30: Connect to MySQL database







                                                                                                                   return to top of exercise


(1.3) Create Model


In this step, you are going to use the Rails Generator to create a model for the application. The helloworld application requires a Message model for representing messages.

<Study point: What is MVC?>

Model-view-controller (MVC) is an architectural pattern used in software engineering. In complex computer applications that present a large amount of data to the user, a developer often wishes to separate data (model) and user interface (view) concerns, so that changes to the user interface will not affect data handling, and that the data can be reorganized without changing the user interface. The model-view-controller solves this problem by decoupling data access and business logic from data presentation and user interaction, by introducing an intermediate component: the controller.

<Study point: What is a Model?>

In the context of MVC pattern, a Model represents domain objects such as message, school, product, etc.  A model has attributes and methods.  The attributes represents the characteristics of the domain object, for example, a message model might have length, creator as attributes. The methods in a model contains some business logic.   Most models have corresponding database tables.  For example, a message model will have messages table.

<Study point: What is a Generator?>

Rails' use of runtime reflection and metaprogramming feature of Ruby language eliminates much of the boilerplate code that you would otherwise have to create. You can often avoid writing boilerplate code by using the built-in generator scripts of Rails to create it for you. This leaves you with more time to concentrate on the code that really matters--your business logic.


1. Generate a Model.

Figure-1.31: Generate a model

Figure-1.32: Rails generator

2. Study what files have been created.

Figure-1.33: message.rb

<Study point: What is ActiveRecord?> 

ActiveRecord is the object-relational mapping (ORM) layer that connects business objects (models) to database tables. It is an implementation of the Active Record pattern described by Martin Fowler.


3. Find out what methods are available from ActiveRecord::Base class through Rails Console. (This is an optional step.)

Figure-1.34: Open Rails Console

  <Study point: What is Rails Console?>

The Rails console gives you access to your Rails Environment, for example, you can interact with the domain models of your application as if the application is actually running.  Things you can do include performing find operations or creating a new model object and then saving it to the database.

Warning:
Click at the Console prompt before typing anything, to ensure the cursor is indeed in the Console.

Figure-1.35: Display methods of ActiveRecord class

>> ActiveRecord.methods.size
=> 155
>> ActiveRecord.methods
=> ["load_all!", "const_get", "as_load_path", "public_instance_methods", "pretty_print_cycle", "autoload?", "mattr_reader", "freeze", "const_missing", "included_modules", "==", "mattr_writer", "__jtrap_kernel", "attr_accessor_with_default", "attr_internal_reader", "instance_method", "public_class_method", "ancestors", "included_in_classes", "<", "list", "yaml_as", "extended", "protected_method_defined?", ">", "delegate", "===", "private_instance_methods", "hash", "attr_internal_writer", "class_variables", "<=", "method_defined?", "instance_methods", "class_variable_defined?", "pretty_print", "name", "attr_internal", "private_method_defined?", "attr_internal_accessor", "const_set", "autoload", "include?", "protected_instance_methods", "module_eval", "included", "mattr_accessor", "yaml_tag_class_name", "initialize_copy", "attr_internal_naming_format=", "append_features", "<=>", "constants", "private_class_method", "trap", "yaml_tag_read_class", "to_s", "synchronize", "public_method_defined?", "class_eval", ">=", "const_missing_without_dependencies", "attr_internal_naming_format", "const_defined?", "unloadable", "const_missing_with_dependencies", "local_constants", "parent", "parent_name", "model_name", "alias_method_chain", "local_constant_names", "parents", "alias_attribute", "returning", "present?", "subclasses_of", "`", "to_yaml_style", "extend_with_included_modules_from", "include_class", "to_param", "java_kind_of?", "remove_subclasses_of", "__jtrap", "with_options", "copy_instance_variables_from", "to_yaml_properties", "taguri", "acts_like?", "try", "metaclass", "tap", "to_yaml", "blank?", "duplicable?", "to_json", "dclone", "to_yaml_node", "handle_different_imports", "instance_variable_names", "extended_by", "to_query", "instance_values", "load_with_new_constant_marking", "require_association", "require_dependency", "require_or_load", "require", "decode64", "encode64", "decode_b", "b64encode", "pretty_print_inspect", "pretty_print_instance_variables", "methods", "breakpoint", "enable_warnings", "silence_stream", "extend", "nil?", "object_id", "method", "tainted?", "is_a?", "instance_variable_defined?", "instance_variable_get", "pretty_inspect", "instance_variable_set", "silence_stderr", "display", "send", "private_methods", "enum_for", "equal?", "com", "type", "instance_of?", "id", "taint", "class", "instance_variables", "require_library_or_gem", "org", "to_a", "__send__", "=~", "protected_methods", "inspect", "__id__", "frozen?", "java", "respond_to?", "instance_eval", "untaint", "clone", "daemonize", "to_enum", "singleton_methods", "eql?", "instance_exec", "silence_warnings", "suppress", "dup", "kind_of?", "javax", "debugger", "public_methods"]
>>
Figure-1.36: Display methods of ActiveRecord

                                                                                                                   return to top of exercise


(1.4) Create database table through migration


<Study point: What is a migration?> 

Migrations can manage the evolution of a schema. It's a solution to the common problem of adding a field to make a new feature work in your local database, but being unsure of how to push that change to other developers and to the production server. With migrations, you can describe the transformations in self-contained classes that can be checked into version control systems and executed against another database that might be one, two, or five versions behind.  A simple migration example looks as following:

  class AddSsl < ActiveRecord::Migration
    def self.up
      add_column :accounts, :ssl_enabled, :boolean, :default => 1
    end

    def self.down
      remove_column :accounts, :ssl_enabled
    end
  end

The migration example above will add a column called ssl_enabled to the accounts table and remove it again, if you‘re backing out of the migration. It shows how all migrations have two class methods up and down that describes the transformations required to implement or remove the migration. These methods can consist of both the migration specific methods, like add_column and remove_column, but may also contain regular Ruby code for generating data needed for the transformations. (Quoted from ActiveRecord:Migration section of api.rubonrails.org)

1. Create the database table through migration

Figure-1.41: Migration


Figure-1.44: Migrate database to the current version

Figure-1.45: Migration

Trouble-shooting: If you are experiencing the problem shown in Figure-1.45t below (java.net.SocketException: java.net.ConnectException: Connection refused), it is highly likely because the MySQL Server has not been started. Solution: Start the MySQL server as described in section (0.2) Start MySQL Server.


Figure-1.45t: Rake error when the MySQL Server has not been not started

2. Verify the messages table has been created.  (This is an optional step.)

Figure-1.46: Expand the table

Figure-1.47: messages table is now created

<Study point: What is schema_migration table?> 

Rails versions 2.0 and prior used to create a table called schema_info when using migrations. This table contained the version of the schema as of the last applied migration.

Starting with Rails 2.1, the schema_info table is (automatically) replaced by the schema_migrations table, which contains the version numbers of all the migrations applied.


3. Display the column names of the messages table. (This is an optional step.)

>> Message.column_names
=> ["id", "greeting", "created_at", "updated_at"]
>>
Figure-1.48: Display column names of the Message class




                                                                                                                   return to top of exercise


(1.5) Create a Controller


In this step, you are going to use the Rails Generator to create a controller to interact with the model.  Also, you are going to add scaffolding code, which provides a simple CRUD interface for creating, reading, updating, and deleting entries in the blog.

<Study point: What is a Controller (or Action Controller)?>

Action Controllers are the core of a web request in Rails. They are made up of one or more actions that are executed on request and then either render a template or redirect to another action.  An action is defined as a public method on a controller, which will automatically be made accessible to the web-server through Rails Routes.

A sample controller could look like the one below.  There are two actions defined - index and sign.

  class GuestBookController < ActionController::Base
    def index
      @entries = Entry.find(:all)
    end

    def sign
      Entry.create(params[:entry])
      redirect_to :action => "index"
    end
  end

Actions, by default, render a template in the app/views directory corresponding to the name of the controller and action after executing code in the action. For example, the index action of the GuestBookController in the above example would render the template app/views/guestbook/index.html.erb by default after populating the @entries instance variable.

Unlike index, the sign action will not render a template. After performing its main purpose (creating a new entry in the guest book), it initiates a redirect instead. This redirect works by returning an external "302 Moved" HTTP response that takes the user to the index action.

The index and sign actions above represent the two basic action archetypes used in Action Controllers: Get-and-show and do-and-redirect. Most actions are variations of these themes.



1. Generate Controller

Figure-1.51: Generate a controller

Figure-1.52: Create a controller

Figure-1.53: Result of creating a controller

2. Add an action to the controller.
class HelloController < ApplicationController
  def say_hello
    @hello = Message.new(:greeting => "Hello World!")
  end
end
Code-1.54 say_hello action is added


Figure-1.55: say_hello action is added

NetBeans tip: If you type def and press tab key, it will generate the def ... end code template for you. Enter say_hello in place of method_name, and click on down arrow to go to the next empty line.

If you type Mes and press ctrl-space, it will open a pop-up window. Click on Message message to get the class. Type a dot, and a n, and click on return to get the template for the new method with attributes, type the real attributes in place of attributes, and click on enter to confirm your typing and go to the end of the line.

Mac OS users tip: As ctrl_space chocks with the system shortcut for Spotlight, you may use cmd-backslash for code completion if you have an English keyboard.

Otherwise you may redefine the shortcut, as ctrl-shift-space for example, in Preferences>Keymap>Search for Code.
Another solution is to switch temporarily to English keyboard with cmd-space, then use cmd-backslash (lower key close by the return key) to get completion code, and return to native keyboard with cmd-space.

                                                                                                                   return to top of exercise

(1.6) Write a View


<Study point: What is a View (or Action View)?>

View is represented by a set of templates.  Templates share data with controllers through mutually accessible variables.  A template can be either in the form of *.rhtml (sometimes called RHTML file) or *.erb file.  (The *.erb file is searched first by Rails.)

1. Create say_hello.rhtml template.
Please make sure you are right clicking Views->hello not Views.  This is important since the say_hello.rhtml file has to be created under Views->hello directory since that is where the Rails will look for the say_hello.rhtml file.
Figure-1.61: Create new RHMTL file


Figure-1.62: Create say_hello.rhtml

2. Modify the IDE generated say_hello.rhtml file to display the greeting message and current time.
<%#
# To change this template, choose Tools | Templates
# and open the template in the editor.
%>

My greeting message is <%= @hello.greeting %>
<br/>
The current time is <%= Time.now %>
Code-1.63: Modified say_hello.rhtml


Figure-1.64: Modified say_hello.rhtml

NetBeans tip: If you type re and press tab key, it will generate the <%= > code template for you.
Next you may use code completion as already described to enter the rest of the code.

                                                                                                                   return to top of exercise


(1.7) Set URL routing


<Study point: URL routing> 

The default Rails mapping of URLs to controller actions is very simple and easy to understand. Rails tries very hard to present the user with pretty URLs. Rails URLs are simple and straightforward, not long and cryptic. Even so, you can still customize your URLs by using the Rails routing facility. Rails' URL routing is flexible enough to allow you to create virtually any URL mapping scheme. The Rails routing facility is pure Ruby code that even allows you to use regular expressions. Because Rails does not use the web server's URL mapping, your custom URL mapping will work the same on every web server. 

1.  Add a URL routing.

Figure-1.71: A new route

2. Delete index.html under Public directory.

Figure-1.72: Delete index.html under Public directory

Figure1.74: Save all

                                                                                                                   return to top of exercise

(1.8) Build and run the application


1. Run the application.

Figure-1.81: Run the application

Figure-1.83: Correct path is not specified

2. Use the correct path.

Figure-1.84: say_hello.rhtml is displayed

3. Add index action to the controller.
class HelloController < ApplicationController
  def index
    say_hello  # Call say_hello action method
    render :action=>'say_hello'  # Render a template from the say_hello action method
  end
  def say_hello
    @hello = Message.new(:greeting => "Hello World!")
  end
end
Code-1.85: Add index action to the controller

Figure-1.86: Add index action to the controller

NetBeans tip: For generating code template for render : action => "say_hello" code block, type ra and press tab key, then type the action method.

4. Access the application without controller and action now.

Figure-1.87: say_hello.rhtml is displayed


Trouble-shooting: If you are experiencing the problem shown in Figure-1.88 below, it is highly likely because the MySQL database server is not running. 
Solution: Start the MySQL database server as described (0.1) Start MySQL database server.


Figure-1.88: Error condition when the database server is not running

Trouble-shooting: If you are experiencing the problem shown in Figure-1.89 below, it is highly likely because the migration has not been performed after database is created.
Solution: Perform the migration as described (1.4) Migrate the database.


Figure-1.89: Error condition when the database is not present

Trouble-shooting: If you are seeing the Figure-1.90 below (instead of correct page represented by Figure-1.84 above), it is because you have not deleted the index.html under Public node as described above.
Solution: Delete index.html under Public node.


Figure-1.90: index.html in Public node is displayed

Trouble-shooting: If you are seeing the Figure-1.91 below (instead of correct page represented by Figure-1.84 above), it is because did not set the correct routing in the Configuration/routes.rb as described above.
Solution: Set the correct routing.


Figure-1.91: Routing error

Trouble-shooting: If you see the error condition as shown in Figure-1.92 below, one possible explanation might be because the say_hello did not have quote as shown in Code-1.93 below. Solution is to have quote as shown in Code-1.94 below.


Figure-1.92: Error condition

class HelloController < ApplicationController
  def index
    say_hello
    render :action=>say_hello # Incorrect syntax
  end
  def say_hello
    @hello=Message.new(:greeting=>"Hello World!")
  end
end
Figure-1.93: Incorrect usage of render method

class HelloController < ApplicationController
  def index
    say_hello
    render :action=>'say_hello' # Correct syntax
  end
  def say_hello
    @hello=Message.new(:greeting=>"Hello World!")
  end
end
Figure-1.94: Correct usage of render method

                                                                                                                   return to top of exercise


Solution


The solution of this exercise is provided as a ready-to-build NetBeans project -  <LAB_UNZIP_DIR>/rails_basics/solutions/exercise1/helloworld.  You should be able to build and run the project. (You might still have to create the database as described in step 1.2 above and the migrate the database described in step 1.4 above before you run the application.)

Summary


In this exercise, you have learned how to build a simple Rails application going through the development steps of creating model. controller, and view.  You also learned how to migrate a database.

                                                                                                                              return to the top


Exercise 2: Add another field to a Model


In this exercise, you are going to add another field to the Message model (in other words, to add another column to the messages table) of the "helloworld" application you built in Exercise 1.

Key learning points:
Tasks to be performed:
  1. Add another field to a table through migration
  2. Modify the controller
  3. Modify the view
  4. Save the changes and refresh the browser
  5. Display log file
  6. Modify the view

(2.1) Add another field to a table through migration


1. Generate a new migration.

Figure-2.11: Perform Generation

Figure-2.12: Generate a migration

Figure-2.13: Generation is done

You might wonder "How does Rails know that I want to add a new field to the messages table given that I did not mention messages table?  Actually you did.  When you name the migration file as AddNameToMessages, Rails figures that you want to add a field to the messages table by looking at the "..ToMessages".  As an experiment, if you name your migration as RandomMigrationName, you will have to add "add_column :mesages, ..." yourself.

2. Migrate database.

Figure-2.14: Migrate the database to the current version

Figure-2.15: Migration is done

3. Verify that the new column name is now added to the messages table. (This is an optional step.)

Figure-2.16: Verify that the name column is present

                                                                                                                   return to top of exercise

(2.2) Modify the controller


In this step, you are going to make a change in the say_hello action so that it assigns a value to the name attribute of the @hello .

1. Modify the HelloController.
class HelloController < ApplicationController
  def index
    say_hello
    render :action=>'say_hello'  # Render a template from the say_hello action method
  end
  def say_hello
    @hello = Message.new(:greeting => "Hello World!")
    @hello.name = "Sang Shin"
  end
end
Code-2.21: Modified controller


Figure-2.22: Modified controller

                                                                                                                   return to top of exercise


(2.3) Modify the view


In this step, you are going to modify the say_hello.rhtml to display the name attribute of the @hello instance variable.

1. Modify the say_hello.rhtml as shown in Code-2.31 and Figure-2.32 below. The code fragment that needs to be added is highlighted in bold and red-colored font.

<%#
# To change this template, choose Tools | Templates
# and open the template in the editor.
%>

My greeting message is <%= @hello.greeting %>
<br/>
The current time is <%= Time.now %>
<br/>
My name is <%= @hello.name %>
Code-2.31: Modified say_hello.rhtml


Figure-2.32: Modified say_hello.rhtml

                                                                                                                   return to top of exercise


(2.4) Save the changes and Refresh the browser


1. Save the changes.

Figure-2.41: Save the changes

2. Refresh the browser to see the result.
Note that you did not have to recompile, redeploy the application to see the change.  Instead, you save the change and then refresh the browser.  This is one of the high development productivity features of Rails.


Figure-2.42: Result is displayed

                                                                                                                   return to top of exercise

(2.5) Display log file


The log files could be used for debugging purpose.

1. Log file as it was using earlier versions of Rails


Figure-2.51: Display the development.log file in earlier version of Rails

Contrary to what happened with previous versions of Rails, the request parameters are now suppressed with backtraces silencers, hence they are no more automatically logged.

2. Display the development.log file.

Figure-2.52a: Detection of Binary File

Figure-2.52b: Display the development.log file in Rails 2.3.2

3. Regain access to parameters
class HelloController < ApplicationController
  def index
    say_hello
    render :action=>'say_hello'
  end
  def say_hello
    @hello = Message.new(:greeting => "Hello World!")
    @hello.name = "Sang Shin"

    # As of Rails 2.3.2 logging the params to hello
    logger.debug("PARAMS: #{@hello.inspect}")
    logger.debug(params.inspect)

  end
end
Code-2.53: Modified controller


Figure-2.53: Modified hello_controller.rb

Figure-2.54: Parameters in Glassfish output

You may eventually play with this snippet of code in the controller to get access to the complete set of parameters of the request:

request.env.each do |name, val|
    logger.debug "Header value: #{name} = #{val}"
end

To get a better display in the view, use: <%= debug(request.env)%>
Figure-2.55: Parameters not logged with Glassfish

4. Switch to WEBrick to get the parameters logged

There is a bug in Glassfish which impedes to get the parameters logged. It works with WEBrick or Mongrel. To switch to WEBRick:
Figure-2.56: Changing project properties


Figure-2.57: Switching to WEBRick server

Figure-2.58: Stop the Glassfish server

Figure-2.59: Parameters logged in development.log file with WEBrick

                                                                                                                   return to top of exercise


(2.6) Modify the view


In this step, you are going to modify say_hello.rhtml so that the contents can be printed multiple times.  (Yes, it is a bit of meaningless exercise but the goal is to show how natural the code looks leveraging the power of Ruby language.)

1. Modify the say_hello.rhtml as shown in Code-2.61 and Figure-2.62 below. The code fragment that needs to be modified is highlighted in bold and red-colored font.

<%#
# To change this template, choose Tools | Templates
# and open the template in the editor.
%>

<% 4.times do |count|  %>
  Counter <%= count %>
  <br/>
  My greeting message is <%= @hello.greeting %>
  <br/>
  The current time is <%= Time.now %>
  <br/>
  My name is <%= @hello.name %>
  <br/>
<% end %>
Code-2.61: Modified view

NetBeans tip: For generating code template for <%     %>, type r and press tab key.


Figure-2.62: Modified view

2. Save all.



3. Refresh the browser.

Figure-2.63: Result of display modified view

                                                                                                                   return to top of exercise

Solution


The solution of this exercise is provided as a ready-to-build NetBeans project -  <LAB_UNZIP_DIR>/rails_basics/solutions/exercise2/helloworld.  You should be able to build and run the project. (You might still have to create the database as described in step 1.2 above and the migrate the database described in step 1.4 above before you run the application.)

Summary


In this exercise, you have learned how to add a new field to a Model through database migration.

                                                                                                                    return to the top


Exercise 3: Add another template to the application


In this exercise, you are going to add another template, say_goodbye.html.erb, to the application.

Key learning points:
Tasks to be performed:
  1. Create a new template, "say_goodbye.html. erb"
  2. Modify existing template, "say_hello.rhtml"
  3. Add a new action to the controller, "hello_controller.rb"
  4. Save all changes and refresh the browser

(3.1) Create a new template


1. Create say_goodbye.html.erb file.

Figure-3.11: Create a new *.html.erb file

Figure-3.12: Give a name to the new template

2. Modify the IDE generated say_goodbye.html.erb file.
<%#
# To change this template, choose Tools | Templates
# and open the template in the editor.
%>

<%= @goodbye.greeting %>

<%= link_to "Go to Hello", :action=>"say_hello" %>
Code-3.13: Modified say_goodbye.html.erb


Figure-3.14: Modified say_goodbye.html.erb

                                                                                                                   return to top of exercise


(3.2) Modify existing template


1. Modify say_hello.rhtml as shown in Code-3.21 and Figure-3.22 below.  The code fragment that needs to be added is highlighted in bold and red-colored font.

<%#
# To change this template, choose Tools | Templates
# and open the template in the editor.
%>

<% 4.times do |count|  %>
  Counter <%= count %>
  <br/>
  My greeting message is <%= @hello.greeting %>
  <br/>
  The current time is <%= Time.now %>
  <br/>
  My name is <%= @hello.name %>
  <br/>
<% end %>

<%= link_to "Go to Goodbye", :action=>"say_goodbye" %>
Code-3.21: Modified say_hello.rhtml


Figure-3.22: Modified say_hello.rhtml

NetBeans tip: NetBeans comes with extensive ready-to-use code templates for Ruby and Rails programming.  For adding <%= link_to  .. %>, just type lia and press tab key.  For adding <%= .. %>, type re and press tab key.  Of course, you can create your own.  For the listing of these code templates, select Tools->Options (Netbeans->Preferences on a Mac) and then select Editor and Code Templates and then select Language option from the drop-down menu.  (Figure-3.23 below)


Figure-3.23: Code templates

                                                                                                                   return to top of exercise


(3.3) Add a new action


1. Modify hello_controller.rb as shown in Code-3.31 and Figure-3.32 below.  The code fragment that needs to be added is highlighted in bold and red-colored font.

class HelloController < ApplicationController
  def index
    say_hello  # Call say_hello action method
    render :action=>'say_hello'  # Render a template from the say_hello action method
  end
  def say_hello
    @hello = Message.new(:greeting => "Hello World!")
    @hello.name = "Sang Shin"
   
    # As of Rails 2.3.2 logging the params to hello
    logger.debug("PARAMS: #{@hello.inspect}")
    logger.debug(params.inspect)
  end
  def say_goodbye
    @goodbye = Message.new(:greeting=>"Goodbye")
  end
end
Code-3.31: Modified hello_controller.rb


Figure-3.32: Modified hello_controller.rb

                                                                                                                   return to top of exercise

(3.4) Save all the changes and refresh the browser


1. Click Save All icon.  (Figure-3.41 below)


Figure-3.41: Save all changes

2. Refresh the browser.

Figure-3.42: Click Go to Goodbye link.

3. Go to Hello template.

Figure-3.43: Go to Hello

                                                                                                                   return to top of exercise


Solution


The solution of this exercise is provided as a ready-to-build NetBeans project -  <LAB_UNZIP_DIR>/rails_basics/solutions/exercise3/helloworld.  You should be able to build and run the project.

By the way, if you want to know which helloworld project you are running (if you are running multiple of them), you can hover your mouse over the project to find out which is which. (Figure-3.44 below)


Figure-3.44: Find out which directory the project is under

Summary


In this exercise, you have learned how to add a new template to the application and how to link templates through link_to helper.

                                                                                                                    return to the top

Exercise 4: Build and run "helloname" application


In this exercise, you are going to learn how to display input form fields using form_tag helper in a template. You will also learn how to access input form parameters.

Learning points:
Tasks to be performed:
  1. Create Ruby on Rails NetBeans project
  2. Create new database
  3. Create a model
  4. Migrate database
  5. Create a controller
  6. Write templates
  7. Set URL routing and delete index.html
  8. Build and run the application

(4.1) Create Ruby on Rails NetBeans project


1.   Create Ruby on Rails NetBeans project.
2. Give project a name.

Figure-4.11: Give a name to the project

                                                                                                                   return to top of exercise

(4.2) Create database


1.   Create database for the project.



                                                                                                                   return to top of exercise


(4.3) Create model


1.   Generate a model.


Figure-4.31: Generate a model

                                                                                                                   return to top of exercise


(4.4) Migrate the database


1. Right-click the helloname project node and choose Migrate Database > To Current Version.   This will create users database table.



                                                                                                                   return to top of exercise



(4.5) Create a Controller


1. Generate Controller


Figure-4.51: Generate controller

2. Add an action to the controller.
class HelloController < ApplicationController
  def respond
    @user = User.new(params[:user])
    @user.save
  end
end
Code-4.52: respond action is added to the HelloController



NetBeans tip: For generating code template for def .. end code block, type def and press tab key.

                                                                                                                   return to top of exercise


(4.6) Write templates


1. Create index.html.erb.

Figure-4.61: Create index.html.erb file.

2. Modify IDE generated index.html.erb file as shown in Code-4.62 below.  The code fragment that needs to be added is highlighted in bold and red-colored font.  The :user represents a User model class and the :name and :age represent attributes of the model class.

<%#
# To change this template, choose Tools | Templates
# and open the template in the editor.
%>

<% form_tag :action=>'respond' do %>
  <p>
    <label>Enter your name:<br/>
      <%= text_field :user, :name %>
    </label>
  </p>
  <p>
    <label>Enter your age:<br/>
      <%= text_field :user, :age %>
    </label>
  </p>
  <p><%= submit_tag 'Submit' %> </p>
<% end  %>
Code-4.62: Modified index.html.erb




NetBeans tip: For generating code template for the <% form_tag :action=>'respond' .. do %> code block, type ft and press tab key.
For <% ... %>, type r and press tab key.
For <%= ... %>, type re and press tab key.

Warning: The code template for form-tag is buggy. See below how to change it.

Figure-4.62a: Accessing ft template.

Figure-4.62b: Changing ft template.


3. Create respond.html.erb.
4. Modify IDE generated respond.html.erb file as shown in Code-4.64 below.  The code fragment that needs to be added is highlighted in bold and red-colored font.

<%#
# To change this template, choose Tools | Templates
# and open the template in the editor.
%>

My name is <%= @user.name %>
<br/>
My age is <%= @user.age %>
Code-4.64: Modified respond.html.erb

                                                                                                                   return to top of exercise


(4.7) Set the URL routing and delete index.html


1. Add a URL routing.

Figure-4.71: A new route

2. Delete index.html under Public directory.
3. Save all changes.
                                                                                                                   return to top of exercise


(4.8) Build and run the application


1. Run the application.

Figure-4.81: Enter values into the input form fields.

Figure-4.82: Name and age are displayed

Trouble-shooting:  If you see the following error condition, just refresh the page again.


Figure-4.83: Error condition

Trouble-shooting: If you see the following error condition as shown in Figure-4.84 below, it is highly likely because you have used the params incorrectly as shown Code-4-85 below.  Correctly use it as shown in Code-4.86 below.


Figure-4.84: Error when incorrect usage of params

This is an incorrect way of using params.

class HelloController < ApplicationController
  def respond
    @user = User.new(@params[:user])
    @user.save
  end
end
Code-4.85: Incorrectly used params

This is a correct way of using params.

class HelloController < ApplicationController
  def respond
    @user = User.new(params[:user])
    @user.save
  end
end
Code-4.86: Correctly used params

Trouble-shooting:  If you see the following error condition, it is likely because you have not performed database migration. Perform it and refresh the browser.


Figure-4.87: Error condition when database migration has not been performed

                                                                                                                   return to top of exercise


Solution


The solution of this exercise is provided as a ready-to-build NetBeans project -  <LAB_UNZIP_DIR>/rails_basics/solutions/exercise4/helloname.  You should be able to build and run the project. (After opening the project, you still have to create the database as described in step 4.2 above and the migrate the database described in step 4.4 above before you run the application.)


Summary


In this exercise, you have learned how to display input form fields using form_tag helper.  You also learned how to access the values of input form parameters.


Homework Exercise (for people who are taking Sang Shin's "Ruby on Rails Development online course")


1. The homework is to write your own simple Rails application as following (something very similar to helloname application above).
2. Send the following files to railshomeworks@javapassion.com with Subject as RailsHomework-rails_basics.

                                                                                                                    return to the top