- •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
DEBUGGING HINTS 244
Logger is a simple logging framework that ships with recent versions of Ruby. (You can get more information by typing ri Logger at a command prompt or by looking in the standard library documentation in Programming Ruby [TFH05].) For our purposes, it’s enough to know that we can generate log messages at the warning, info, error, and fatal levels. We can then decide (probably in an environment file) which levels of logging to write to the log files.
logger.warn("I don't think that's a good idea") logger.info("Dave's trying to do something bad") logger.error("Now he's gone and broken it") logger.fatal("I give up")
In a Rails application, these messages are written to a file in the log directory. The file used depends on the environment in which your application is running. A development application will log to log/development.log, an application under test to test.log, and a production app to production.log.
14.6Debugging Hints
Bugs happen. Even in Rails applications. This section has some hints on tracking them down.
First and foremost, write tests! Rails makes it easy to write both unit tests and functional tests (as we saw in Chapter 13, Task T: Testing, on page 184). Use them, and you’ll find that your bug rate drops way down. You’ll also decrease the likelihood of bugs suddenly appearing in code that you wrote a month ago. Tests are cheap insurance.
Tests tell you whether something works or not, and they help you isolate the code that has a problem. Sometimes, though, the cause isn’t immediately apparent.
If the problem is in a model, you might be able to track it down by running the offending class outside the context of a web application. The script/console script lets you bring up part of a Rails application in an irb session, letting you experiment with methods. Here’s a session where we use the console to update the price of a product.
depot> ruby script/console
Loading development environment. irb(main):001:0> pr = Product.find(:first)
=> #<Product:0x248acd0 @attributes={"image_url"=>"/old_images/sk..." irb(main):002:0> pr.price
=> 29.95
irb(main):003:0> pr.price = 34.95 => 34.95
irb(main):004:0> pr.save => true
Report erratum
DEBUGGING HINTS 245
Logging and tracing are a great way of understanding the dynamics of complex applications. You’ll find a wealth of information in the development log file. When something unexpected happens, this should probably be the first place you look. It’s also worth inspecting the web server log for anomalies. If you use WEBrick in development, this will be scrolling by on the console you use to issue the script/server command.
You can add your own messages to the log with the Logger object described in the previous section. Sometimes the log files are so busy that it’s hard to find the message you added. In those cases, and if you’re using WEBrick, writing to STDERR will cause your message to appear on the WEBrick console, intermixed with the normal WEBrick tracing.
If a page comes up displaying the wrong information, you might want to dump out the objects being passed in from the controller. The debug helper method is good for this. It formats objects nicely and makes sure that their contents are valid HTML.
<h3>Your Order</h3>
<%= debug(@order) %>
<div id="ordersummary" >
. . .
</div>
Finally, for those problems that just don’t seem to want to get fixed, you can roll out the big guns and point irb at your running application. This is normally available only for applications in the development environment.
To use breakpoints:
1.Insert a call to the method breakpoint at the point in your code where you want your application to first stop. You can pass this method a string if you’d like—this becomes an identifying message later.
2.On a convenient console, navigate to your application’s base directory, and enter the command4
depot> ruby script/breakpointer
No connection to breakpoint service at druby://localhost:42531 (DRb::DRbConnError)
Tries to connect will be made every 2 seconds...
Don’t worry about the “No connection” message—it just means that your breakpoint hasn’t hit yet.
4. Under OS X, you’ll need an additional option unless you want to wait for about a minute for the breakpointer to spring to life:
depot>ruby script/breakpointer -c druby://127.0.0.1:42531
Report erratum
WHAT’S NEXT 246
3.Using a browser, prod your application to make it hit the breakpoint method. When it does, the console where breakpointer is running will burst into life—you’ll be in an irb session, talking to your running web application. You can inspect variables, set values, add other breakpoints, and generally have a good time. When you quit irb, your application will continue running.
If you’re expecting a full debugger at this point—well, sorry. At the time of writing, all you can do with breakpointer is examine and change program state when it hits a breakpoint.
By default, the breakpointer uses a local network connection to talk between your application and the breakpointer client. You might be able to use the - s option when you run breakpointer to connect to an application on another machine, but you’ll need to make sure that there are no firewalls in the way.
14.7What’s Next
The chapter that follows looks at all the programmatic support you have while writing a Rails application. This is followed by an in-depth look at Migrations.
If you’re looking for information on Active Record, Rails’ object-relational mapping layer, you need Chapters 17 through 19. The first of these covers the basics, the next looks at intertable relationships, and the third gets into some of the more esoteric stuff. They’re long chapters—Active Record is the largest component of Rails.
These are followed by two chapters about Action Controller, the brains behind Rails applications. This is where requests are handled and business logic lives. After that, Chapter 22, Action View describes how you get from applicationlevel data to browser pages.
But wait (as they say), there’s more! The new style of web-based application makes use of JavaScript and XMLHttpRequest to provide a far more interactive user experience. Chapter 23, The Web, V2.0, tells you how to spice up your applications.
Rails can do more than talk to browsers. Chapter 24, Action Mailer, shows you how to send and receive e-mail from a Rails application, and Chapter 25, Web Services on Rails, on page 583, describes how you can let others access your application programmatically using SOAP and XML-RPC.
We leave two of the most important chapters to the end. Chapter 26, Securing Your Rails Application, contains vital information if you want to sleep at night after you expose your application to the big, bad world. And Chapter 27, Deployment and Production, contains the nitty-gritty details of putting a Rails application into production and scaling it as your user base grows.
Report erratum