At the Forge - Debugging Rails Applications
I have been using logfiles to assist me in debugging and development for years, starting long before I began to use Rails. But logfiles allow you to see only what has happened in the past, passively. One of the best tools in a Rails developer's toolbox is the console, an interactive command-line interface that allows you to query, execute and test commands and variable values. If you are familiar with Ruby's “irb” for interactive work, the console will be familiar to you.
The console often is the first place that I write any code. It puts you in a context similar to that of a controller, allowing you to talk to the database via ActiveRecord, creating (and modifying and destroying) objects and assigning them.
For example, I often play around with associations and named scopes within the console, testing that I easily can retrieve one object through another or retrieve a subset of objects using a method call. For example, if I have a Person object and a Vehicle object, I should be able to say Person.new.vehicles in the console and get the empty array. Or, I should be able to use a named scope to say Person.men, retrieving only the men from the database.
I also use the console a great deal to test objects for validity. The valid? method for ActiveRecord objects, coupled with the save! method that raises an exception when a save goes wrong, allows me to test objects to see whether ActiveRecord believes they're valid, and why. For example, if I say:
I should get a list (not formatted beautifully, I admit) of the validations that have failed—generally indicating which attributes need to be set in order to save the person successfully. True, you always could invoke the errors method on an object after a failed save, but I find this to be faster and more obvious, which is precisely why I'm in the console.
I often use the console to piece together the methods I am going to use or just to experiment with code that eventually will go into a class or module. If you modify a model definition while you're in the console, you need to reload models with:
so that the console will be synchronized with the current state of the source code.
By default, the console operates in the development environment, so that when you write:
you are talking to the development database.
I should note that there are a number of Ruby gems designed to improve the irb experience. One of these is wirble, which colorizes and otherwise improves the irb interface. I have been using it for a while and find it hard to use irb without its various improvements.
A newer entry is looksee, which provides a new lp (lookup path) method that shows each of the methods an object responds to, categorized and sorted as a list of ancestors. Using lp has made it easier for me to know just which class or module definition I need to inspect to investigate a particular method.
If you want to use the console for a production environment, which I often do when debugging problems on a production server, you will need to state the name of the environment explicitly:
I should add that recent versions of Rails include a similar command, dbconsole, which allows you to talk directly to the relational database for the environment to which you're connected. I often use dbconsole instead of typing mysql or psql (depending on the system I'm using). However, it's important to remember that when you work in the Rails console, the objects are subject to validations and other integrity checks that are not present in your raw connection to the relational database. So for safety's sake, it's usually a good idea to do things through Ruby, rather than the database. (Although if your database supports transactions, you can get some element of safety by doing all modifications within a BEGIN-COMMIT block.)
The console, of course, is good for testing code, but you cannot run your entire Rails application inside the console. There are times, however, when you wish you could drop into the console just for a portion of your Rails application to poke around inside it. True, you could use logging statements to write the current state of affairs to the logfile, but there's nothing like interactively exploring an application from the inside to give you a better feeling about how it is working (or not).
The solution to this problem is the deceptively simple ruby-debug gem, which you can install (like all Ruby gems) by saying:
sudo gem install ruby-debug
You then need to include the gem. This typically is done in the development and/or test environment, but not in the production environment, for obvious reasons. Inside of config/environments/development.rb (or test.rb), you add:
- Papa's Got a Brand New NAS
- Applied Expert Systems, Inc.'s CleverView for TCP/IP on Linux
- Panther MPC, Inc.'s Panther Alpha
- Simplenote, Simply Awesome!
- GENIVI Alliance's GENIVI Vehicle Simulator
- The Tiny Internet Project, Part III
- Rogue Wave Software's TotalView for HPC and CodeDynamics
- NethServer: Linux without All That Linux Stuff
- Sometimes My Office Goes with Me
- Jetico's BestCrypt Container Encryption for Linux