
- •Contents
- •Preface to the Second Edition
- •Introduction
- •Rails Is Agile
- •Finding Your Way Around
- •Acknowledgments
- •Getting Started
- •The Architecture of Rails Applications
- •Models, Views, and Controllers
- •Active Record: Rails Model Support
- •Action Pack: The View and Controller
- •Installing Rails
- •Your Shopping List
- •Installing on Windows
- •Installing on Mac OS X
- •Installing on Linux
- •Development Environments
- •Rails and Databases
- •Rails and ISPs
- •Creating a New Application
- •Hello, Rails!
- •Linking Pages Together
- •What We Just Did
- •Building an Application
- •The Depot Application
- •Incremental Development
- •What Depot Does
- •Task A: Product Maintenance
- •Iteration A1: Get Something Running
- •Iteration A2: Add a Missing Column
- •Iteration A3: Validate!
- •Iteration A4: Prettier Listings
- •Task B: Catalog Display
- •Iteration B1: Create the Catalog Listing
- •Iteration B4: Linking to the Cart
- •Task C: Cart Creation
- •Sessions
- •Iteration C1: Creating a Cart
- •Iteration C2: A Smarter Cart
- •Iteration C3: Handling Errors
- •Iteration C4: Finishing the Cart
- •Task D: Add a Dash of AJAX
- •Iteration D1: Moving the Cart
- •Iteration D3: Highlighting Changes
- •Iteration D4: Hide an Empty Cart
- •Iteration D5: Degrading If Javascript Is Disabled
- •What We Just Did
- •Task E: Check Out!
- •Iteration E1: Capturing an Order
- •Task F: Administration
- •Iteration F1: Adding Users
- •Iteration F2: Logging In
- •Iteration F3: Limiting Access
- •Iteration F4: A Sidebar, More Administration
- •Task G: One Last Wafer-Thin Change
- •Generating the XML Feed
- •Finishing Up
- •Task T: Testing
- •Tests Baked Right In
- •Unit Testing of Models
- •Functional Testing of Controllers
- •Integration Testing of Applications
- •Performance Testing
- •Using Mock Objects
- •The Rails Framework
- •Rails in Depth
- •Directory Structure
- •Naming Conventions
- •Logging in Rails
- •Debugging Hints
- •Active Support
- •Generally Available Extensions
- •Enumerations and Arrays
- •String Extensions
- •Extensions to Numbers
- •Time and Date Extensions
- •An Extension to Ruby Symbols
- •with_options
- •Unicode Support
- •Migrations
- •Creating and Running Migrations
- •Anatomy of a Migration
- •Managing Tables
- •Data Migrations
- •Advanced Migrations
- •When Migrations Go Bad
- •Schema Manipulation Outside Migrations
- •Managing Migrations
- •Tables and Classes
- •Columns and Attributes
- •Primary Keys and IDs
- •Connecting to the Database
- •Aggregation and Structured Data
- •Miscellany
- •Creating Foreign Keys
- •Specifying Relationships in Models
- •belongs_to and has_xxx Declarations
- •Joining to Multiple Tables
- •Acts As
- •When Things Get Saved
- •Preloading Child Rows
- •Counters
- •Validation
- •Callbacks
- •Advanced Attributes
- •Transactions
- •Action Controller: Routing and URLs
- •The Basics
- •Routing Requests
- •Action Controller and Rails
- •Action Methods
- •Cookies and Sessions
- •Caching, Part One
- •The Problem with GET Requests
- •Action View
- •Templates
- •Using Helpers
- •How Forms Work
- •Forms That Wrap Model Objects
- •Custom Form Builders
- •Working with Nonmodel Fields
- •Uploading Files to Rails Applications
- •Layouts and Components
- •Caching, Part Two
- •Adding New Templating Systems
- •Prototype
- •Script.aculo.us
- •RJS Templates
- •Conclusion
- •Action Mailer
- •Web Services on Rails
- •Dispatching Modes
- •Using Alternate Dispatching
- •Method Invocation Interception
- •Testing Web Services
- •Protocol Clients
- •Secure and Deploy Your Application
- •Securing Your Rails Application
- •SQL Injection
- •Creating Records Directly from Form Parameters
- •Avoid Session Fixation Attacks
- •File Uploads
- •Use SSL to Transmit Sensitive Information
- •Knowing That It Works
- •Deployment and Production
- •Starting Early
- •How a Production Server Works
- •Repeatable Deployments with Capistrano
- •Setting Up a Deployment Environment
- •Checking Up on a Deployed Application
- •Production Application Chores
- •Moving On to Launch and Beyond
- •Appendices
- •Introduction to Ruby
- •Classes
- •Source Code
- •Resources
- •Index
- •Symbols

CHECKING UP ON A DEPLOYED APPLICATION 625
Once you’ve set up your virtual host block for Apache, restart it, and you’ll be off to the races.
# On your server(s) $ sudo httpd restart
Rinse, Wash, Repeat
Once you’ve gotten this far, your server is ready to have new versions of your application deployed to it anytime you would like. All you need to do is check your changes into Subversion and then redeploy:
# On your local computer $ rake remote:deploy
If for some reason you need to step back in time and go back to a previous version of your application, you can use
# On your local computer $ rake remote:rollback
You’ve now got a fully deployed application and can deploy as needed to update the code running on the server. Each time you deploy your application, a new version of it is checked out on the server, some symlinks are updated, and the Mongrel instances are restarted.
27.6Checking Up on a Deployed Application
Once you have your application deployed, you’ll no doubt need to check up on how it’s running from time to time. There are two primary ways you’ll do this. The first is to monitor the various log files output by both your front-end web server and the Mongrel instances running your application. The second is to connect to your application using script/console.
Looking at Log Files
To get a quick look at what’s happening in your application, you can use the tail command to examine log files as requests are made against your application. The most interesting data will usually be in the log files from the application itself. When running multiple instances of your application with Mongrel, the logged output from all the servers is aggregated into the mongrel.log file.
Assuming that your application is deployed into the same location we showed earlier, here’s how you look at your running log file.
# On your server
$ cd /Library/Rails/myapplication/current/ $ tail -f log/mongrel.log
Report erratum

PRODUCTION APPLICATION CHORES 626
Sometimes, you need a lower-level information—what’s going on with the data in your application? When this is the case, it’s time to break out the most useful live server debugging tool.
Using Console to Look at a Live Application
You’ve already created a large amount of functionality in your application’s model classes. Of course, you created these to be used by your application’s controllers. But you can also interact with them directly. The gateway to this world is the script/console script. You can launch it on your server with
# On your server
$ cd /Library/Rails/myapplication/current/ $ ruby ./script/console production
Loading production environment.
irb(main):001:0> p = Product.find_by_title("Pragmatic Version Control") => #<Product:0x24797b4 @attributes={. . .}
irb(main):002:0> p.price = 32.95 => 32.95
irb(main):003:0> p.save => true
Once you have a console session open, you can poke and prod all the various methods on your models. You can create, inspect, and delete records. In a way, it’s like having a root console to your application.
27.7Production Application Chores
Once you put an application into production, there are a few chores that you need to take care of to keep your application running smoothly. These chores aren’t automatically taken care of for you. Luckily you can automate them.
Dealing with Log Files
As an application runs, it will constantly add data to its log file. Eventually, the log files can grow extremely large. To overcome this, most logging solutions can roll over log files to create a progressive set of log files of increasing age. This will break up your log files into manageable chunks that can be archived off or even deleted after a certain amount of time has passed.
The Logger class supports rollover. However, each Mongrel process has its own Logger instance. This sometimes causes problems, because each logger tries to roll over the same file. Rather than use the built-in rollover mechanism, set up your own periodic script (triggered by cron or the like) to first copy the contents of the current log to a different file and then truncate it.
Clearing Out Sessions
The session handler in Rails doesn’t do automated housekeeping. This means that once the data for a session is created, it isn’t automatically cleared out
Report erratum

MOVING ON TO LAUNCH AND BEYOND 627
after the session expires. This can quickly spell trouble. The default file-based session handler will run into trouble long before the database-based session handler will, but both handlers will create an endless amount of data.
Since Rails doesn’t clean up after itself, you’ll need to do it yourself. The easiest way is to run a script periodically. If you keep your sessions in files, the script needs to look at when each session file was last touched and then delete the older ones. For example, you could put the following command into a script that will delete files that haven’t been touched in the last 12 hours.
# On your server
$ find /tmp/ -name 'ruby_sess*' -ctime +12h -delete
If your application keeps session data in the database, your script can look at the updated_at column and delete rows accordingly. You can use script/runner to execute this command.
> RAILS_ENV=production ./script/runner \ 'ActiveRecord::Base.connection.delete(
"DELETE FROM sessions WHERE updated_at < now() - 12*3600")'
Keeping on Top of Application Errors
You might want to look at the exception notification plugin to set up a way of e-mailing support staff when exceptions are thrown in your application. Install using
depot> ruby script/plugin install exception_notification
Add the following to your application controller.
class ApplicationController < ActionController::Base include ExceptionNotifiable
# ...
Then set up a list of people to receive notification e-mails in your environment.rb file.
ExceptionNotifier.exception_recipients = %w(support@my-org.com dave@cell-phone.company)
You’ll need to ensure that Action Mailer is configured to send e-mail, as we describe starting on page 567.
27.8Moving On to Launch and Beyond
Once you’ve set up your initial deployment, you’re ready to finish the development of your application and launch it into production. You’ll likely set up additional deployment servers, and the lessons you learn from your first deployment will tell you a lot about how you should structure later deployments. For example, you’ll likely find that Rails is one of the slower components of your system—more of the request time will be spent in Rails than in
Report erratum

MOVING ON TO LAUNCH AND BEYOND 628
waiting on the database or filesystem. This indicates that the way to scale up is to add machines to split up the Rails load across.
However, you might find that the bulk of the time a request takes is in the database. If this is the case, you’ll want to look at how to optimize your database activity. Maybe you’ll want to change how you access data. Or maybe you’ll need to custom craft some SQL to replace the default Active Record behaviors.
One thing is for sure: every application will require a different set of tweaks over its lifetime. The most important activity to do is to listen to it over time and discover what needs to be done. Your job isn’t done when you launch your application. It’s actually just starting.
Report erratum