Skip to main content

Rails: The luxury line to professional Web sites

Gary Pollice, Professor of Practice, Worcester Polytechnic Institute
Author photo
Gary Pollice is a professor of practice at Worcester Polytechnic Institute, in Worcester, MA. He teaches software engineering, design, testing, and other computer science courses, and also directs student projects. Before entering the academic world, he spent more than thirty-five years developing various kinds of software, from business applications to compilers and tools. His last industry job was with IBM Rational Software, where he was known as "the RUP Curmudgeon" and was also a member of the original Rational Suite team. He is the primary author of Software Development for Small Teams: A RUP-Centric Approach, published by Addison-Wesley in 2004. He holds a B.A. in mathematics and an M.S. in computer science.

Summary:  from The Rational Edge: This companion article to the July 2007 piece on the programming language Ruby describes Rails, a framework, built on top of Ruby for developing, maintaining, and deploying Web applications. This content is part of the The Rational Edge.

Date:  15 Aug 2007
Level:  Introductory
Also available in:   Chinese

Activity:  1676 views
Comments:  

illustration Last month I offered a bit of a detailed look at the Ruby programming language -- a dynamic language that has become a favorite among many software developers. This month I take a look at the Ruby-based framework for building Web applications, Rails. Rails illustrates the value of frameworks, the generative power of dynamic languages like Ruby, and how following convention over configuration yields numerous advantages to developers.

The quest for more value for the effort

Since programmers began writing programs, they have been looking for ways to deliver more value in their programs for the amount of effort put into them. In the last fifty years, there have been a lot of theories generated about how to do this. We've certainly seen high-level languages evolve. But the incremental improvements over lower-level languages haven't made us sit up, smack our foreheads, and say "Wow!" Even the dynamic languages, which in the '90s were placed in the "Very High-Level Language" (VHLL) category, haven't offered the type of gains most of us want and need in order to meet the increasing demand for software.

We've advanced our ideas about how to improve programmer productivity with reusable frameworks, cross-cutting technology such as aspect-oriented programming, component-based development, service-oriented architectures, model-driven architecture, and more. Each of these offers something when used properly. While we still haven't achieved the "programmerless programs" some have imagined, we have made advances in improving programmer productivity. Still, none of these advances has given us the 10-100X gains that we need.

Before continuing I want to make it clear that Rails doesn't give us this either, in the general case. However, in the domain of building Web applications, I've seen examples where Rails does deliver this sort of productivity.

What is Rails?

Rails is a framework, built on top of Ruby, for developing, maintaining, and deploying Web applications. A framework can be loosely defined as an application generator or partial application that can be modified for different uses (within a particular domain). That's it! Rails isn't a general-purpose extension to Ruby. It's designed for a specific domain -- the Web. Rails is based upon some basic principles that make it very easy to do common things and possible to do those things that are outside of its basic scope. Rails rewards programmers for following the conventions its designers have established by generating a large part of a typical Web application with very little programming necessary. You can amaze your colleagues and managers by producing Web applications that are expertly crafted even if you're a novice at Web technology. 1

Rails, also called "Ruby on Rails" in several articles, is the brain-child of David Heinemeier Hansson, a Danish Web application developer who was building Web applications using Ruby. He realized that there was a lot of commonality in the way he constructed the applications. Like many good developers, he began to look for ways to automate his work. The result of this effort was the first release of Rails. 2 Hansson based Rails on an application called Basecamp. 3 In fact, Rails was extracted from Basecamp and generalized by abstracting the commonality and encapsulating the variability. This is the approach we generally use when building domain-specific languages.

Rails is an open source project with a very active developer and user community. 4 If you want to get under the covers of Rails, you're able to do it and work with others to enhance it. But if you just want to build professional Web applications with minimal effort, you can just install Rails on your system and get to work. Oh yes, building applications with Rails is also fun! Remember how excited you were when you built your first useful program? I got that feeling again the first time I used Rails.

A simple example

Every book or article on Rails seems to begin with a simple example. I'm not going to present one in detail, but will show you some highlights of one from the most popular book on Rails, Thomas and Hansson's Agile Development with Rails. 5 The example is a basic on-line shopping site. The products we want to sell have a title, description, image, and price. After about a half hour of reading and following the text I had the application to the point where I could add products to the database, edit them, and remove them. The application follows a typical Model-View-Controller (MVC) architecture and Rails makes it easy to keep the responsibilities separate since it automatically generates the proper source files in separate directories where their purpose is obvious.

The body of the Web page I ended up with looks like Figure 1. There are only two products in my catalog now, but you can see a few things about the page. If the product has an image, like my rendition of a stick-robot, it appears. The first part of the description is displayed, along with any embedded HTML tags. Each product has three links after it so we can see how the product looks when we display it, edit the item, or remove it. There is also a link to create a new product. We are clearly not ready to spring this onto the world, but we can start working with the stakeholders who are providing the requirements for our application. This allows us to use an iterative approach to getting some requirements, implementing them, reviewing the work, and making changes for the next iteration.

Figure shows an initial Rails-based Web page with basic elements in place

Figure 1: Product catalog administration page

While the visual polish of my Web page might not be awe-inspiring, what I had to do to get to this point is amazingly little. I measure my effort by the number of commands I had to enter on my terminal, the number of lines of Ruby code that I had to write, and the amount of HTML and embedded Ruby (ERb) lines I had to write. I did take a couple of shortcuts by copying the Cascading Style Sheets (CSS) file from the Thomas and Hansson book's downloads and don't count the lines in that file in my estimates. Table 1 shows the results of my measurement.

Table 1: Effort to get to maintaining the products


Countable ItemCount
Commands8
Ruby LOC23
HTML and ERb LOC30

The count in Table 1 has been approximated somewhat since I experimented a bit with my code. However, even if I wrote twice as much Ruby code, the total number of lines that I typed into an editor or the command line of my terminal shell is less than 100 lines. What, you might ask, did I really get for those few dozen lines? Consider the following list:

  • A populated MySQL database 6
  • The Web pages to list the products and allow maintenance of them
  • A well-structured MVC application
  • Validation of the fields in the product catalog (positive price, non-blank title and description)
  • An application that I can easily modify and test in a development environment without having to start and stop servers

I find even more exciting the things I did not have to do:

  • I did not have to write a single line of SQL code, yet my application is backed by a relational database.
  • I only had to write a validation method to ensure the price was valid.
  • I did not have to create special code to update my application code when the database schema changed.

I am not a Web application developer. (I've been a bit behind the curve when it comes to learning the technologies since I've focused on other aspects of software engineering. There are just so many things you can do in the time you have available.) But, with just a little knowledge of Ruby and HTML, I'm well on my way to impressing my students with my Web development skills.

Rails principles

How does Rails deliver so much functionality with so little effort required by the developer? One principle of reusability is that there is an inverse relationship between generality and reusability. If you want to make a component or system more reusable -- that is, having larger reusable elements -- you narrow the domain to which it applies. This is the first thing I noticed about Rails. It is not a framework that lets you build a Web application any way you choose; rather, it is designed to support a particular approach to Web application development. If you follow the guidelines you can achieve a tremendous amount of reuse. If you stray from the guidelines, your amount of reuse will diminish.

So, what are the guidelines, or principles of Rails? There aren't many, but they appear throughout the framework. Let's look at each of them in the next sections.

Model-View-Controller

The Model-View-Controller architecture is well-known among software developers. It was the basis of early graphical user interface (GUI) systems, such as appeared in the Smalltalk-80 environment. The concept is simple; we separate the system into three distinct parts as shown in Figure 2.

Figure shows relationships of model-view-controller architecture

Figure 2: Model-View-Controller architecture

The MVC architecture separates the responsibilities in an application into three distinct parts. The model is responsible for maintaining the state of the application. It doesn't just retrieve and store the data, it ensures consistency. Business logic that must be applied to the data is encapsulated within the model. The view is responsible for presenting the model in one or more formats to the user. This allows the model to be show in different ways, depending upon the user's needs. The controller is responsible for making sure the other components do the right things at the right time. It receives the requests from the user and dispatches them to the appropriate place. MVC is a robust, efficient architecture for many types of applications, including client/server Web applications.

When you stick to the Rails conventions you have a perfect separation of concerns into these three components. Figure 3 shows a partial layout of my sample application. You can see that the application has separate directories for each component, and one for any helpers needed to support them.

Figure shows sample application folders and files layout

Figure 3: Partial application structure

At this point in development, there is a single controller, the admin controller. Rails knows which controller to invoke by the current URL in the browser. In this case, it's the part of the URL after the Web server. When I'm testing my application, I point my browser at http://localhost:3000/admin, and localhost:3000 connects to the server I'm using -- in this case, the default WEBrick server that comes with Rails. My Rails application's controller directs the request to the AdminController class. If you're interested in what this class contains, you can look at the file in the archive accompanying this article. You should be able to match most of the methods in this class to the links on the Web page shown in Figure 1. Most of the real work is done by the ApplicationController class that AdminController extends. You don't have to worry if you don't understand the details. The file defining AdminController, admin_controller.rb, is one of the larger files in my application, and I didn't write a single line of it. It was completely generated by Rails with a single command. 7

The view for a Web application is the Web pages that are presented to the user. Rails generates a good bit of the Web pages for you, but you still need to know some basic HTML and enough Ruby to write a bit of ERb. There isn't much unique to the view in Rails. You simply create a .rhtml (Ruby HTML) file for each action.

The model is quite simple at this point of my application; there is only one table in the database for products and a product has the four properties I mentioned earlier. I decided to make the image URL an optional property so I do no validation on it. All other fields are tested for validity. The complete text of the product.rb file follows. Not very big, is it?

class Product < ActiveRecord::Base
  validates_presence_of :title, :description
  validates_numericality_of :price
  validates_uniqueness_of :title, :message => "We already have that in our catalog"
  
  protected
  def validate
    errors.add(:price, "must be worth something") if price.nil? || price < 0.01
  end
end

The first three validates_ methods are Rails built-in methods and the validate method is automatically invoked on any product that will go into the system. I had to add the check to see if the prices were at least $.01.

How, you may wonder, did the table for the products get created if I didn't write any SQL? Rails has a somewhat magical component called the Active Record. 8 Active Record is an object-relational mapping (ORM) that follows a standard ORM model. It is basically an abstract implementation of the ActiveRecord design pattern. 9 That is, tables map to classes, objects map to rows, and object properties map to columns. Active Record, like Rails in general, adopts a standard way of managing the mapping. It doesn't support complete generality without some additional effort. However, if you're willing to adopt its standard defaults, there's very little you have to do. The following code shows the file that creates the table:

class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.column :title, :string
      t.column :description, :text
      t.column :image_url, :string
    end
  end

  def self.down
    drop_table :products
  end
end

The only lines I wrote for this were the three t.column.... lines. These define the title, description, and image URL properties. To get the database created and configured, I did the following:

  1. From the command line, I entered:

    mysqladmin -u root create depot_development

    This created my development database.

  2. I entered the following command from my application's root directory:

    ruby script/generate model product

    This created the PRODUCT table in the database. It also created several files, including the product.rb file shown above, and a file called 001_create_products.rb in the application's db/migrate directory. This file is the one shown in the previous listing.

  3. I edited the file to add the three column definitions.

  4. I entered the command:

    rake db:migrate

    This created the columns in the PRODUCT table. rake is a make-like command used by Rails.

Every time you need to update the database schema, you generate a migration in a fashion similar to the above sequence. Each migration file starts with a sequence number one greater than the previous migration file, and that number corresponds to the schema version kept in a special table in the database. Now you can extend the database and rollback changes with minimal effort. Rails does it for you.

Ok, enough about MVC, which is the heart of a Rails application. Let's move on to some of the other principles.

Convention over configuration

I've already illustrated this principle in action. A Rails application adheres to several conventions quite strictly. Some of these conventions are as simple as naming conventions while others are more about the application's architecture. Rails has a very clear notion of how a Web application is built, and it uses defaults based upon this model. The assumptions about defaults make it possible to generate a much larger part of the application than the framework might otherwise be able to. It also avoids the need for the developer to go through a lengthy configuration process to set up the proper environments for development, testing, and deployment. There are a couple of configuration files that you might modify to add MIME types or other information that falls outside of common usage scenarios. The only file you will probably have to modify is the database.yml file that describes the key parameters for your development, testing, and deployment environments. When I created my application this file was generated with default values as shown in the following listing.

# MySQL (default setup).  Versions 4.1 and 5.0 are recommended.
#
# Install the MySQL driver:
#   gem install mysql
# On MacOS X:
#   gem install mysql -- --include=/usr/local/lib
# On Windows:
#   gem install mysql
#       Choose the win32 build.
#       Install MySQL and put its /bin directory on your path.
#
# And be sure to use new-style password hashing:
#   http://dev.mysql.com/doc/refman/5.0/en/old-client.html
development:
  adapter: mysql
  database: depot_development
  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: mysql
  database: depot_test
  username: root
  password:
  host: localhost

production:
  adapter: mysql
  database: depot_production
  username: root
  password: 
  host: localhost

Notice that the code uses three separate databases for each environment. The comment above the test environment configuration points out an additional feature of developing applications with Rails. Testing is a first-class citizen in the Rails development process. When you extend and change your application according to the conventions, Rails helps you out by generating automated tests for you that you run with the rake utility. The tests are automatically run in a separate environment that interferes with neither your development environment nor your production environment.

The DRY principle

The final principle that shows up in Rails applications is Don't Repeat Yourself (DRY). Good designers and programmers follow this principle as a matter of practice. They know that doing something once, in a single place, makes their designs simpler and their work much more maintainable.

The way Rails organizes and generates the applications, following the DRY principle is easy when you follow the conventions. When you learn to navigate the code base for one Rails application, you've gained the knowledge you need to understand any other Rails application that follows the conventions. Nothing is repeated. There is a single place for everything and it all makes sense.

But will it scale?

Whenever I encounter something as seemingly simple as Rails, I wonder if it's really able to work in real, industrial-strength environments. I've seen too many tools that promise great productivity gains. They look good on "toy" projects, but fail horribly when you apply them to real problems. I've read quite a few success stories with Rails, but I really became convinced last year when we had a success story at our university.

One of my colleagues at Worcester Polytechnic Institute (WPI) has been developing an intelligent tutoring system, called Assistments, to assist teachers and students at various levels in different subjects. As in many states, Massachusetts elementary and high school students must pass a series of standardized tests during their scholastic careers, ultimately as a prerequisite for high school graduation. These tests, called MCAS 10 tests, are given at different grade levels to assess the students' abilities in key learning areas. The Assistments 11 tutoring system has been shown to be effective in helping students learn the necessary skills. Last year the Assistments system was used by a small number of students in the Worcester, MA area, but my colleague's Assistments team soon needed to prepare for a much larger-scale deployment.

Assistments is a typical client/server Web application. It not only helps the teachers and students using it, but it supports researchers in developing new learning techniques and providing measurement capabilities. By last year, Assistments consisted of over 50,000 lines of code (LOC) of mainly Java code. The code had numerous packages and classes that had been developed over a few years by graduate and undergraduate students. Unfortunately, there was not much continuity in the development team and the code was becoming extremely unmanageable -- i.e., becoming more fragile each day. How was the team going to get it to the quality needed for a large-scale rollout?

There were three possibilities. First, we could continue to try to maintain and extend the current system. This was not considered for long. Second, we could rewrite the system from scratch or try to evolve the existing architecture into the system we needed. This would be a Java effort. Initially, this was the approach the team considered taking.

A third possibility came up when one of the graduate students working on the Assistments team suggested rewriting the system using Rails. As you can imagine, his colleagues and the professor directing the group were nervous about that. The student spent a few weeks developing a core application that had most of the basic functionality of the existing Assistments system. He wrote less than a thousand lines of code to get to this point.

The team was sold. They adopted a solid development process and went to work. The new system has all the functionality of the old system with several additions, including a much better user interface. The last information I received indicated that there were less than 5,000 LOC for the team to write and maintain. This is better than a 10X productivity increase, and there have been fewer defects reported against the system than average.

Yes, Rails is not a toy.

Final thoughts

The idea of generating programs is not new. But we have improved the technology greatly in recent years. Rails is one very effective framework for creating a particular type of program in a clear, consistent way, with minimal effort. You can expect to see more systems like Rails appear for different domains. It just makes good business sense. In fact, there are other entries in the Web application builder arena. There are two frameworks, similar to Rails, written in PHP. These are Symfony and CakePHP. 12 Another interesting entry that recently appeared is Project Zero, an incubator project within IBM. Project Zero is not a generator, but provides conventions and structure that reminds me of Rails. 13

If you haven't taken the plunge into developing Web applications, I hope this column gives you some food for thought and encourages you to take a little time out to have some fun and get on track with Rails.

Notes

1 There are a lot of tutorials that will help you on your way. See the Resources section at the end of this article for some of them. Follow a tutorial and you'll be amazed at how easy building a Web application can be.

2 The first beta version of Rails was released in July, 2004. Rails 1.0 was released to the world in December 2005. The examples in this article use version 1.2.2.

3 http://www.basecamphq.com

4 See http://dev.rubyonrails.org for the Rails repository.

5 This is described in detail in Chapter 6 of the book. See Thomas and Hansson, et al., Agile Development with Rails, Pragmatic Bookshelf: 2006.

6 Rails supports most relational database management systems. MySQL is the default, but changing to another database is trivial.

7 You will also notice a standard naming convention that all of the Rails created files use. This makes it trivial to locate and determine the purpose of each file.

8 Actually, the Active Record is one of the Ruby Gems that you can use for any application. Rails has simply adopted it and standardized its use in Rails applications.

9 A description of the ActiveRecord design pattern is at http://www.martinfowler.com/eaaCatalog/activeRecord.html

10 Massachusetts Comprehensive Assessment System. See http://www.doe.mass.edu/mcas/testitems.html

11 See http://www.assistments.org

12 See http://www.symfony-project.com/ and http://cakephp.org/

13 See http://www.projectzero.org


Resources

Learn

  • There many books available on Rails. Four that I am familiar with are:
    • Agile Web Development with Rails, 2ed., Dave Thomas and David Heinemeier Hansson, The Pragmatic Programmers LLC, 2006, ISBN 0977616630.
    • Build Your Own Ruby on Rails Web Applications, Patrick Lenz, SitePoint Pty. Ltd, 2007, ISBN 0975841955.
    • Rails for Java Developers, Stuart Halloway and Justin Gehtland, Pragmatic Programmers LLC, 2007, ISBN 097761669.
    • Rails Cookbook, Rob Orsini, O'Reilly Media Inc., 2007, ISBN 0596527314.

  • There are many online resources available. I recommend starting with the Ruby on Rails home page, http://www.rubyonrails.org/ and following the useful links from there.

Discuss

About the author

Author photo

Gary Pollice is a professor of practice at Worcester Polytechnic Institute, in Worcester, MA. He teaches software engineering, design, testing, and other computer science courses, and also directs student projects. Before entering the academic world, he spent more than thirty-five years developing various kinds of software, from business applications to compilers and tools. His last industry job was with IBM Rational Software, where he was known as "the RUP Curmudgeon" and was also a member of the original Rational Suite team. He is the primary author of Software Development for Small Teams: A RUP-Centric Approach, published by Addison-Wesley in 2004. He holds a B.A. in mathematics and an M.S. in computer science.

Comments



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational
ArticleID=247782
ArticleTitle=Rails: The luxury line to professional Web sites
publish-date=08152007
author1-email=gpollice@cs.wpi.edu
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers