Chapter 4, Rails Revealed
As you might have gathered from Chapter 1, Introducing Ruby on Rails, quite a bit of thought has been put into the code base that makes up the Rails framework. Over time, many of the internals have been rewritten, which has improved their speed and efficiency, and allowed the implementation of additional features, but the original architecture remains largely unchanged. This chapter will shed some light on the inner workings of Rails.
Rails encourages the use of a different environment for each of the stages in an application’s lifecycle — development, testing, and production. If you’ve been developing Web applications for a while, this is probably how you operate anyway; Rails just formalizes these environments.
In the development environment, changes to an application’s source code are immediately visible; all we need to do is reload the corresponding page in a web browser. Speed is not a critical factor in this environment; instead, the focus is on providing the developer with as much insight as possible into the components involved in displaying each page. When an error occurs in the development environment, the developer is able to tell at a glance which line of code is responsible for the error, and how that particular line was invoked. This capability is provided by the stack trace (a comprehensive list of all the method calls leading up to the error), which is displayed when an unexpected error occurs.
In testing, we usually refresh the database with a baseline of dummy data each time a test is repeated — this ensures that the results of the tests are consistent, and that behavior is reproducible. Unit and functional testing procedures are fully automated in Rails.
When we test a Rails application, we don’t view it using a traditional web browser. Instead, tests are invoked from the command line, and can be run as background processes. The testing environment provides a dedicated environment in which these processes can operate.
By the time your application finally goes live, it should be well tested, so that all (or at least most) of the bugs have been eliminated. As a result, updates to the code base should be infrequent, which means that the production environments can be optimized to focus on performance. Tasks such as writing extensive logs for debugging purposes should be unnecessary at this stage. Besides, if an error does occur, you don’t want to scare your visitors away with a cryptic stack trace — that’s best kept for the development environment.
As the requirements of each of the three environments are quite different, Rails stores the data for each environment in entirely separate databases. So at any given time, you might have:
- live data with which real users are interacting in the production environment
- a partial copy of this live data that you’re using to debug an error or develop new features in the development environment
- a set of testing data that’s constantly being reloaded into the testing environment
Let’s look at how we can configure our database for each of these environments.