Saturday, March 24, 2007

Web Development: Ruby on Rails


Ruby on Rails has grown enormously in popularity over the last couple of years. This article, the first of a six-part series, will introduce you to its principles and show you how to use it. It is excerpted from chapter 15 of the Ruby Cookbook, written by Lucas Carlson and Leonard Richardson (O'Reilly, 2006; ISBN: 0596523696). Copyright © 2006 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.
Ruby on Rails is unquestionably Ruby's killer app. It can take a lot of credit for lifting Ruby from obscurity outside its native Japan. No other programming language can boast a simple web application framework that also has almost all of that languages developer mindshare.* This chapter demonstrates the principles underlying basic Rails usage (in recipes like Recipe 15.6), gives Rails implementations of common web application patterns (Recipes 15.4 and 15.8) and shows how to use standard Ruby tools from within Rails (Recipes 15.22 and 15.23).
Despite its quality and popularity, Rails does not bring anything new to web development. Its foundations are in standard programming patterns like ActiveRecord and Model-View-Controller. It reuses many preexisting Ruby libraries (like Rake and ERb). The power of Rails is in combining these standard techniques with a ruthless dedication to automating menial tasks, and to asserting resonable default behaviors.
If Rails has a secret, it's the power of naming conventions. The vast majority of web applications are CRUD applications: create, read, update, and delete information from a database. In these types of applications, Rails shines. You start with a database schema and with almost no code, but Rails ties together many pieces with naming conventions and shortcuts. This lets you put meat on your application very quickly.
Because so many settings and names can be sensibly derived from other pieces of information, Rails has much less "paperwork" than other frameworks. Data that's implicit in the code or the database schema doesn't need to be specified anywhere else. An essential part of this system is the ActiveSupport system for pluralizing nouns (Recipe 15.7).
Where naming conventions can't do the job, Rails uses decorator methods to declare relationships between objects. This happens within the Ruby classes affected by those relationships, not in a bloated XML configuration file. The result is a smaller, simpler to understand, and more flexible application.
As mentioned above, Rails is built on top of common Ruby libraries, and many of them are also covered elsewhere in this book. These libraries include ActiveRecord (much of Chapter 13, but especially Recipe 13.11), ActionMailer (Recipe 14.5), ERb (Recipe 1.3), Rake (Chapter 19), and Test::Unit (Recipe 17.7). Some of these predate Rails, and some were written for Rails but can be used outside of it. The opposite is also true: since a Rails application can be used for many purposes, nearly every recipe in this book is useful within a Rails program.
Rails is available as the rails gem, which contains libraries and the rails command-line program. This is the program you run to create a Rails application. When you invoke this program (for instance, with rails mywebapp), Rails generates a directory structure for your web application, complete with a WEBrick testing server and unit testing framework. When you use the script/generate script to jumpstart the creation of your application, Rails will populate this directory structure with more files. The code generated by these scripts is minimal and equivalent to the code generated by most IDEs when starting a project.
The architecture of Rails is the popular Model-View-Controller architecture. This divides the web application into three predictably named parts. We'll cover them in detail throughout this chapter, but here's an introductory reference.
The model is a representation of the dataset used by the application. This is usually a set of Ruby classes, subclasses of ActiveRecord::Base, each corresponding to a table in the application database. The first serious model in this chapter shows up in Recipe 15.6. To generate a model for a certain database table, invoke script/generate model with the name of the table, like so:
$ script/generate model users
This creates a file called app/models/users.rb, which defines a User ActiveRecord class as well as the basic structure to unit test that model. It does not create the actual database table.
The controller is a Ruby class (a subclass of ActionController::Base) whose methods define operations on the model. Each operation is defined as a method of the controller.
To generate a controller, invoke script/generate controller with the name of the controller, and the actions you want to expose:
$ script/generate controller user add delete login logout
This command creates a file app/controllers/user_controller.rb, which defines a class UserController. The class defines four stub methods: add, delete, login , and logout, each corresponding to an action the end user can perform on the objects of the underlying User model. It also creates the template for functionally unit testing your controller.
The controller shows up in the very first recipe of this chapter (Recipe 15.1).
The view is the user interface for the application. It's contained in a set of ERb templates, stored in .rhtml files. Most importantly, there is usually one .rhtml file for each action of each controller: this is the web interface for that particular action. The same command that created the UserController class above also created four files in app/views/user/: add.rhtml, delete.rhtml, login.rhtml, and logout.rhtml. As with the UserController class, these start out as stub files; your job is to customize them to present an interface to your application.
Like the controller, the view shows up in the first recipe of this chapter, Recipe 15.1. Recipes like 15.3, 15.5, and 15.14 show how to customize your views.
This division is not arbitrary. If you restrict code that changes the database to the model, it's easy to unit test that code and audit it for security problems. By moving all of your processing code into the controller, you separate the display of the user interface from its internal workings. The most obvious benefit of this is that you can have a UI designer modify your view templates without making them work around a lot of Ruby code.
The best recipes for learning how Model-View-Controller works are Recipe 15.2, which explores the relationship between the controller and the view; and Recipe 15.16, which combines all three.
Here are some more resources for getting started with Rails:
This book's sister publication, Rails Cookbook by Rob Orsini (O'Reilly), covers Rails problems in more detail, as does Rails Recipes by Chad Fowler (Pragmatic Programmers)
Agile Web Development with Rails by Dave Thomas, David Hansson, Leon Breedt, Mike Clark, Thomas Fuchs, and Andrea Schwarz (Pragmatic Programmers) is the standard reference for Rails programmers
The Ruby on Rails web site at http://www.rubyonrails.com/, especially the RDoc documentation (http://api.rubyonrails.org/) and wiki (http://wiki.rubyonrails.com/)

No comments: