/Tools/ RoR: Back on track
07/07/2006 | Filed under Develop > Tools

Even the name, Ruby On Rails, suggests something completely different: not scary, not tiresome but intrinsically valuable.
Toby Boudreaux, reveals how ROR can take the grunt-work out of hand-crafting sites, enabling you to devote yourself to the essential and, importantly, fun aspects of web design…
Ruby on Rails (RoR) is an open source framework for the rapid development, testing, and deployment of agile database-backed web applications. It is the marriage of Ruby, which is an elegant and powerful scripting language, and several classic programming design patterns. The result is a full-stack framework designed around the Model-View-Controller (MVC) design pattern, which means that you can use Ruby in all tiers of your application.
Unlike many similar development efforts, Rails wasn’t developed to be an abstract framework that attempts to solve all problems in all web applications. It simply provides a structure for applications, a set of conventions, and the programmatic glue that so often gets rewritten with each new project.
The hype surrounding Rails has been almost deafening and the core Rails team has received accolades from developers across the web who have taken time to evaluate the framework. A large and active community has formed around the Rails web site, the products of which are extensive documentation, open source plug-ins and enhancements, and a mailing list where the conversation is inspired and advice fl ows freely. Much of the fanfare has been around the speed with which a developer can go from an empty development server to a functional, if not secure or particularly pretty, database-backed web application. The most significant compliment paid to Rails so far has been that it makes web development fun again.
The learning curve for RoR is relatively shallow: while expertise in the Ruby language and familiarity with the MVC design pattern are helpful, they’re by no means essential. In fact, many developers have learned Ruby by way of Rails. The syntax of Ruby and the clarity of the framework are so welcoming and easy to understand that obstacles are essentially absent for even the novice coder. While this clarity is mostly the result of the Ruby language itself, there are many benefits to choosing RoR over pure Ruby.
Installing Rails is simple and there’s very little configuration required. In fact, the foundation provided by Rails reduces configuration to a dozen or so options, most of which are parameters used to establish database connections. The absence of configuration options shouldn’t be interpreted as limiting. Instead, think of the choice to adopt the conventions set forth in Rails as a choice to accept a world of free functionality without sacrificing the agility that’s so important to today’s web developers.
We’re going to use Rails to begin a very simple message board application. We’ll leverage Rails to generate our application directory, create our database tables, and even produce a rudimentary user interface. We won’t cover security, optimisation, testing, or deployment Rails applications here but more information on these topics can always be found on the Rails site at www.rubyonrails.org.
Getting started
Download and install Ruby, rubygems, Rails and the MySQL gem as described on the Rails site at www.rubyonrails.org/down. Choose a location on your computer for your first Rails application and open a terminal window. Change directories to the folder in which you’d like your app to exist. To create the initial skeleton of your application, type the following from the command line: rails message board.
The Rails command generates a folder hierarchy containing the application layout: default JavaScript files; Ruby script files used in generating and destroying Rails components; a test suite for running functional and unit tests on your controllers and models, respectively; auto-loading library folders for third-party extensions, and a small set of configuration files. From your command line, change directories to the new message board folder.
Migrations
Ruby developers organise code into modules in much the same way that Java developers organise code into packages. Of its many components, Rails contains a module for scripting automated database management routines. With the ActiveRecord::Migrations module, you can create and destroy tables, alter table structures and column types, and even migrate from one database system, such as MySQL, to another, such as PostgreSQL.
For our lightweight message board application, we need to generate two database tables: one for discussion threads and another for posts left by users. To begin using migrations, run the migration generator for both by typing:
ruby script/generate migration create_discussions_table
ruby script/generate migration create_posts_table
The migration generator will create files in the db/migrate folder.
Each migration, like everything in Ruby, is a class, specifically a migrations subclass like the ActiveRecord::Migration class. All migrations have two necessary methods: up and down. The up method is used to set up the migration and the down method is used to roll the migration back. We’ll open the db/migrate/01_create_discussion_table.rb file to define our up method to create our discussions table and our down method to destroy the table:
class CreateDiscussionsTable < ActiveRecord::Migration
def self.up
create_table :discussions do |table|
table.column :title, :string, :limit=>100
table.column :created_at, :datetime, :null => false
end
end
def self.down
drop_table :discussions
END
end
Each discussion in our message board only needs a couple of attributes: a title for the discussion and a time at which the discussion was created. Posts are only slightly more complex than discussions. They require four attributes: the textual body of the post; the created_ at stamp; the name of the person leaving the post; and the foreign key that points to the discussion in which the post exists. Define your posts migration so that the up and down methods are as follows:
class CreatePostsTable < ActiveRecord::Migration
def self.up
create_table :posts do |table|
table.column :body, :text
table.column :created_at, :datetime, :null => false
table.column :name, :string, :limit=>100
table.column :discussion_id, :integer, :null => false
end
execute ALTER TABLE posts ADD CONSTRAINT fk_posts
FOREIGN KEY(discussion_id) REFERENCES discussions(id)
end
def self.down
drop_table :posts
end
end
Notice that the up method contains an extra statement: the execute statement. Because we want to maintain referential integrity between our posts and discussions tables, we need to define a foreign key constrain at the database level.
Connecting to your database
The one case where it’s required to configure Rails manually is database connections. The config/database.yml file is used to specify parameters for them and the Rails developers' convention is to have a database for each of the project phases: development, testing, and production. Edit your config file so that the development entry resembles the following:
development:
adapter: mysql
database: messageboard_development
username: rails_net
password: super_secret_password
socket: /path/to/your/mysql.sock
Both the test and production entries should be similar, aside from the database parameter and the user name and password parameters.
To run your migrations and have the Rails framework create your database tables, switch to your command line and type:
rake migrate --trace
When your migration is complete, your databases are ready to go.
The easiest way to get your application up and running is to use the scaffold generator to create the model, view and controller files for each of your data types. From your command line, type:
ruby script/generate scaffold Discussion
ruby script/generate scaffold Post
This will generate the appropriate model, view, and controller files inside the app/models, app/views and app/controllers folders.
Routing rules
Rails relies on URLs and routing rules to determine the course of action for a given request. The controller layer of your Rails application consists of subclasses of ActionController::Base, all of which are defined in your app/controllers folder. Any public method of a controller class is accessible as an action in your Rails application. The standard controller template used in generating scaffolds consists of eight actions: index, list, show, new, create, edit, update, and destroy. These actions are just suggestions and can be changed at will.
1. A List Apart
A List Apart is a legendary web development site focusing on standards, usability, smart design, and elegant programming.
2. Spread Reading
Spread is an online book club and community site with a goal of spreading the love of reading and discussing books of all types.
3. Campfire
The newest product from 37signals, Campfire provides an innovative service addressing the instant messaging needs of groups.
4. Odeo
Odeo enables users to record, share, Podcast, search for and listen to original audio content with both online and standalone audio players.
5. StreetEasy
StreetEasy is an estate agent listlings aggregator and searchable database that makes searching for houses in NYC fun and easy.
Routes are defined in the config/routes.rb file. The default and most common routing convention used in Rails is the :controller/:action/:id route. This route tells Rails to use the URL components immediately following the domain and port as the controller, action and the id of a database record that is subject to the request.
When a controller executes an action, the results of the execution are available to a template with the same name as the action. Templates are organised by controller name in the app/views directory.
Using the default routing rule, a URL such as someserver/friends/ show/1001 would cause the FriendsController.show method to execute. An ID with a value of 1001 would be available to the request. The template file that would be processed and displayed in the browser would be located at app/views/friends/show.rhtml.
One of the nice features of the Rails framework is the inclusion of a fully functional web server called Webrick. Written entirely in Ruby, Webrick is perfect for Rails development because there’s no need to install and configure a typical web server, such as Apache or LightTPD, on your local development machine. You can start Webrick from the command line by typing:
ruby script/server
You can view the (empty) listing of our Discussion records at localhost:30 00/discussions/list.
If you click the ‘New discussion’ link, you’ll be taken to a form that can be used to create a new discussion. Create a discussion called ‘Hello, World!’ and submit the form.
Because our PostController responds to the same default actions as our DiscussionsController, we can view the Post management interface by going to localhost:3000/posts/list.
If you attempt to create a new post by following the ‘New post’ link and submitting the resulting form, Rails will throw a database error. This is because scaffolding does not find relationships between tables on its own, so the foreign key constraint in the posts table that requires a discussion ID will fail. The power of ActiveRecord enables us to easily specify the relationships between tables inside our model classes.
Using ActiveRecord::Base subclasses
Open the app/models/discussion.rb file in a text editor. The code inside defines a simple subclass of the ActiveRecord::Base class. We can add our own methods and properties to this class to specify relationships to other ActiveRecord::Base subclasses.
Rails provides logical function names for establishing relationships. Our Discussion-Post relationship is a classic one-to-many relationship: each discussion has many posts, and each post has one discussion. We must specify the reciprocal sides of this relationship in both the Discussion and the Post classes. You can use the has_many function inside the Discussion class:
class Discussion < ActiveRecord::Base
has_many :posts
end
To the app/models/post.rb file, you can add a belongs_to call to let Rails know that each post belongs to a discussion:
class Post < ActiveRecord::Base
belongs_to :discussion
end
One more step is required to enable your post to be created. We must modify the form used to create posts so that you can choose the discussion to which your post belongs. Open the app/views/discussions/_form.rhtml file.
ActionView templates use embedded Ruby, or ERb (an acronym for embedded Ruby) for server processing. While code in templates can do anything your controller or model code can do, the best practice is to use ERb for simple and clear-view layer programming. View code that is reusable across templates or that contains complex programming should be broken out of templates and put into a centralised location. Rails enables you to create collections of functions in helper files, located in the App/helpers folder. The scaffold generator creates a helper file for each controller, enabling you to add helper functions that are exclusive to one specific controller. Alternatively, you can use the global app/helpers/application_helper.rb file to define global helpers.
Rails includes a useful library of helpers that perform date and time formatting, HTML generation and many additional common tasks. The ActionView::Helpers::FormHelper module enables you to create various HTML form elements inside your templates.
We’ll use a Rails form helper to create a select menu with all discussions listed. Change your app/views/posts/_form.rhtml file according to this example:
<%= error_messages_for post %>
<!--[form:post]-->
<fieldset>
<label for=”post_discussion_id”>Discussion</label>
<%= collection_select(:post, :discussion_id, Discussion.
find(:all), :id, :title) %>
</fieldset>
<fieldset>
<label for=”post_body”>Body</label>
<%= text_area post , body %>
</fieldset >
<fieldset>
<label for=”post_created_at”>Created at</label>
<%= datetime_select post , created_at %>
</fieldset>
<fieldset>
<label for=”post_name”>Name</label>
<%= text_field post , name %>
</fieldset>
<!--[eoform:post]-->
You can now go to your new Post form at localhost:3000/posts/new and add a Post to the ‘Hello, World!’ Discussion.
To make our message board even easier to use, we should modify the app/views/discussions/show.rhtml template to show all Post records for a given Discussion on one page. We’ll use the power of ActiveRecord to select all posts in a given discussion and show them without writing a single line of SQL code.
Modify your app/views/discussions/show.rhtml page so that it matches the following:
<h1>Posts for <%= @discussion.title %></h1>
<ol>
<% for post in @discussion.posts %>
<li>
<div class=”post”>
<h2><%= post.name %> said <%= time_ago_in_
words(post.created_at)%> ago:</h2>
<%= post.body %>
</div>
</li>
<% end %>
</ol>
<%= link_to Add a Post to this Discussion , :
controller=> posts , :action=> new , :discussion_id=>@discussion
%> |
<%= link_to Edit this Discussion , :action => edit , :id =>
@discussion %> |
<%= link_to All Discussions , :action => list %>
Save the file and view the first discussion in your browser at localhost:3000/discussions/show/1.
All Post instances that have been created for the Discussion instance @discussion are available as an array of Post objects. These are pulled from the database automatically when referenced via the @discussion. posts accessor.
Easy to adapt
While far from a feature-complete message board, you can see that it’s quite easy to create web applications using the Ruby on Rails framework. The ease with which you can modify your application is helpful and can be really useful for helping you to meet deadlines. It’s is also fantastic for responding to changes in requirements and adapting to feedback received from clients and users.
The Ruby on Rails framework offers a great deal of value to developers – a fact made apparent by its thriving and enthusiastic community. The popularity is the result of many factors: the productivity boosts are often the initial draw, but Rails brings more than efficiency to the table: Rails makes development fun.
Bookmark with:
Comments
Magic8ball / 26/03/2007 / 20:42
Nice article, can we have more articles on Ruby please
santoshchalla / 13/06/2007 / 07:02
I created the sample message board application but i can not abule to find the replay part.can you ive some idea for that .
Jonathan / 11/02/2009 / 21:09 / http://www.propdata.co.za
Great article! Would however love to read something on django. A framework I've been using for a while now and really prefer to RoR.


