Chapter 1. Rails Environments and Configuration

[Rails] gained a lot of its focus and appeal because I didn’t try to please people who didn’t share my problems. Differentiating between production and development was a very real problem for me, so I solved it the best way I knew how.

—David Heinemeier Hansson

Rails applications are preconfigured with three standard modes of operation: development, test, and production. These modes are basically execution environments and have a collection of associated settings that determine things such as which database to connect to and whether the classes of your application should be reloaded with each request. It is also simple to create your own custom environments if necessary.

The current environment can be specified via the environment variable RAILS_ENV, which names the desired mode of operation and corresponds to an environment definition file in the config/environments folder. You can also set the environment variable RACK_ENV, or as a last resort, you may rely on the default being development. Since this environment setting governs some of the most fundamental aspects of Rails, such as class loading, in order to really understand the Rails way, you should understand its environment settings.

In this chapter, we start by covering Bundler, a tool that manages gem dependencies for your Ruby application. It takes a gem manifest file and is able to fetch, download, and install the gems in the manifest and all child dependencies. Then we move on to how Rails starts up and handles requests, by examining scripts such as boot.rb and application.rb and the settings that make up the three standard environment settings (modes). We also cover some of the basics of defining your own environments and why you might choose to do so.

Note that this book is not written with absolute newcomers to Rails in mind. To make the most out of this book, you should already be at least somewhat familiar with how to bootstrap a Rails application and the meaning of MVC. If you are not, I recommend that you first take advantage of the excellent Ruby on Rails Tutorial website1 by Michael Hartl, another Professional Ruby Series author.

1. http://ruby.railstutorial.org/

1.1 Bundler

Bundler2 is not a technology that is specific to Rails 4, but it is the preferred way to manage your application’s gem dependencies. Applications generated with Rails 4 use Bundler automatically, and you should not need to install the bundler gem separately since it’s a dependency of Rails itself.

2. http://bundler.io

Since we believe that you should use Bundler, figuring out how to not use Bundler is left as an exercise for adventurous and/or nonconformist readers.

One of the most important things that Bundler does is dependency resolution on the full list of gems specified in your configuration, all at once. This differs from the one-at-a-time dependency resolution approach employed by RubyGems and previous versions of Rails, which can (and often did) result in the following hard-to-fix problem:

Assume that your system had the following RubyGem versions installed.

activesupport 4.0.2
activesupport 3.2.11
activemerchant 1.29.3
rails 3.2.11

It turns out that activemerchant 1.29.3 depends on activesupport >= 2.3.14; therefore, when you load it using the gem command (from the RubyGems library) like this,

gem 'activemerchant', '1.29.3'

it results in the loading of activemerchant, as well as the latest compatible versions of its dependencies, including the activesupport 4.0.2 gem, since it is greater than or equal to version 2.3.14. Subsequently, trying to load Rails itself with

gem 'rails', '3.2.11'

results in the following exception at runtime:

can't activate activesupport (= 3.2.11, runtime)
for ["rails-3.2.11"], already activated
activesupport-4.0.2 for ["activemerchant-1.29.3"]

The exception happens because activemerchant has a broader dependency that results in the activation of a version of Active Support that does not satisfy the more narrow dependency of the older version of Rails. Bundler solves this problem by evaluating all dependencies at once and figuring out exactly the right versions of gems to load.

For an interesting perspective concerning the way that Bundler was conceived, make sure to read Yehuda’s blog post on the subject.3

3. http://yehudakatz.com/2010/04/21/named-gem-environments-and-bundler/

1.1.1 Gemfile

Located in the root of your Rails project directory is a Ruby-based gem manifest file named Gemfile. The Gemfile specifies all dependencies of your Rails app, including the version of Rails being used. The basic syntax for the Gemfile is simple:

gem 'kaminari'
gem 'nokogiri'

To load a dependency only in a specific environment, place it in a group block specifying one or more environment names as symbols:

group :development do
  gem 'pry-rails'
end

group :test do
  gem 'capybara'
  gem 'database_cleaner'
end

group :development, :test do
  gem 'rspec-rails'
  gem 'factory_girl_rails'
end


Upgrading from Rails 3

If you’re upgrading from Rails 3, note that Rails 4 no longer uses the assets group for Asset Pipeline–related gems. You will need to move all assets grouped gems inline.


The gem directive takes an optional second argument describing the version of the RubyGem desired. Leaving the version argument off will simply get the latest available stable version, which may not be the latest version available. To include a release candidate or a prerelease gem, you’ll need to specify the version explicitly.

The format of the version argument matches the RubyGem versioning scheme to which you should already be accustomed.

gem 'nokogiri', '1.5.6'
gem 'pry-rails', '> 0.2.2'
gem 'decent_exposure', '~> 2.0.1'
gem 'draper', '1.0.0.beta6'

You can find full instructions on how to craft a version string in the RubyGems documentation.4

4. http://docs.rubygems.org/read/chapter/16

Occasionally, the name of the gem that should be used in a require statement is different from the name of that gem in the repository. In those cases, the :require option solves this simply and declaratively right in the Gemfile.

gem 'webmock', require: 'webmock/rspec'

1.1.1.1 Loading Gems Directly from a Git Repository

Until now we have been loading our gems from https://rubygems.org. It is possible to specify a gem by its source repository as long as it has a .gemspec file in the root directory. Just add a :git option to the call to gem.

gem 'carrierwave', git: '[email protected]:carrierwaveuploader/carrierwave.git'

If the gem source repository is hosted on GitHub and is public, you can use the :github shorthand.

gem 'carrierwave', github: 'carrierwaveuploader/carrierwave'

Gemspecs with binaries or C extensions are also supported.

gem 'nokogiri', git: 'git://github.com/tenderlove/nokogiri.git'

If there is no .gemspec file at the root of a gem’s Git repository, you must tell Bundler which version to use when resolving its dependencies.

gem 'deep_merge', '1.0', git: 'git://github.com/peritor/deep_merge.git'

It’s also possible to specify that a Git repository contains multiple .gemspec files and should be treated as a gem source. The following example does just that for the most common Git repository that fits the criteria—the Rails codebase itself. (Note: You should never actually need to put the following code in a Gemfile for one of your Rails applications!)

git 'git://github.com/rails/rails.git'
gem 'railties'
gem 'action_pack'
gem 'active_model'

Additionally, you can specify that a Git repository should use a particular ref, branch, or tag as options to the git directive:

git 'git://github.com/rails/rails.git',
  ref: '4aded'

git 'git://github.com/rails/rails.git',
  branch: '3-2-stable'

git 'git://github.com/rails/rails.git',
  tag: 'v3.2.11'

Specifying a ref, branch, or tag for a Git repository specified inline uses the same option syntax.

gem 'nokogiri', git: 'git://github.com/tenderlove/nokogiri.git', ref: '0eec4'

1.1.1.2 Loading Gems from the Filesystem

You can use a gem that you are actively developing on your local workstation using the :path option.

gem 'nokogiri', path: '~/code/nokogiri'

1.1.2 Installing Gems

Every time you modify the Gemfile, or more specifically, if you introduce dependencies not yet installed, invoke the install command to ensure that all the dependencies in your Gemfile are available to your Rails application.5

5. rbenv allows you to easily install, manage, and work with multiple Ruby interpreters and it’s a must-have tool for modern Rails developers: https://github.com/sstephenson/rbenv

$ bundle install
Fetching gem metadata from https://rubygems.org/.........
Fetching gem metadata from https://rubygems.org/..
Installing rake (10.1.0)
Installing i18n (0.6.9)
Installing minitest (4.7.5)
Installing multi_json (1.8.2)
Installing atomic (1.1.14)
Installing thread_safe (0.1.3)
Installing tzinfo (0.3.38)
Installing activesupport (4.0.2)
Installing builder (3.1.4)
Installing erubis (2.7.0)
Installing rack (1.5.2)
Installing rack-test (0.6.2)
Installing actionpack (4.0.2)
Installing mime-types (1.25.1)
Installing polyglot (0.3.3)
Installing treetop (1.4.15)
Installing mail (2.5.4)
Installing actionmailer (4.0.2)
Installing activemodel (4.0.2)
Installing activerecord-deprecated_finders (1.0.3)
Installing arel (4.0.1)
Installing activerecord (4.0.2)
Installing coffee-script-source (1.6.3)
Installing execjs (2.0.2)
Installing coffee-script (2.2.0)
Installing thor (0.18.1)
Installing railties (4.0.2)
Installing coffee-rails (4.0.1)
Installing hike (1.2.3)
Installing jbuilder (1.5.2)
Installing jquery-rails (3.0.4)
Installing json (1.8.1)
Installing bundler (1.3.5)
Installing tilt (1.4.1)
Installing sprockets (2.10.1)
Installing sprockets-rails (2.0.1)
Installing rails (4.0.2)
Installing rdoc (3.12.2)
Installing sass (3.2.12)
Installing sass-rails (4.0.1)
Installing sdoc (0.3.20)
Installing sqlite3 (1.3.8)
Installing turbolinks (1.3.1)
Installing uglifier (2.3.2)
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.

The install command updates all dependencies named in your Gemfile to the latest versions that do not conflict with other dependencies.

You can opt to install dependencies, except those in specified groups using the --without option.

$ bundle install --without development test
$ bundle install --without test

1.1.3 Gem Locking

Every time you run bundle install or bundle update, Bundler calculates the dependency tree for your application and stores the results in a file named Gemfile.lock. From that point on, Bundler will only load specific versions of gems that you are using at the moment that the Gemfile was locked—versions that you know will work well with your application.


Note

The Gemfile.lock file should always be checked into version control to ensure every machine running the application uses the exact same versions of gems.6

6. http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/

To illustrate the importance of this, imagine the Gemfile.lock is missing and the application is being deployed to production. Since the dependency tree is nonexistent, Bundler has to resolve all the gems from the Gemfile on that machine. This may install newer gem versions than you tested against, causing unforeseen issues.


1.1.4 Packaging Gems

You can package up all your gems in the vendor/cache directory inside of your Rails application.

$ bundle package

Running bundle install --local in an application with packaged gems will use the gems in the package and skip connecting to rubygems.org or any other gem sources. You can use this to avoid external dependencies at deploy time or if you depend on private gems that are not available in any public repository.

1.1.4.1 Making Gem Dependencies Available to Non-Rails Scripts

Non-Rails scripts must be executed with bundle exec in order to get a properly initialized RubyGems environment.

$ bundle exec guard

As of Rails 4, generating a new application will result in the creation of binstubs for Rails executables, located in the bin folder. A binstub is a script containing an executable that runs in the context of the bundle. This means one does not have to prefix bundle exec each time a Rails-specific executable is invoked. Binstubs are also first class citizens in Rails 4 and should be added into your version control system like any other source code file.

By default, the following stubs are available on every new Rails 4 project:

bin/bundle

bin/rails

bin/rake

bin/spring

1.1.4.2 Upgrading from Rails 3

If you are upgrading from Rails 3 and have generated binstubs using Bundler in the past, you must upgrade your binstubs by running the following commands:

1 bundle config --delete bin # Turn off Bundler's stub generator
2 rake rails:update:bin # Use the new Rails 4 executables
3 git add bin # Add bin/ to source control

To add a binstub of a commonly used executable in your bundle, invoke bundle binstubs some-gem-name. To illustrate, consider the following example:

$ bundle binstubs guard

This example creates a binstub for guard in the bin folder.

 1 #!/usr/bin/env ruby
 2 #
 3 # This file was generated by Bundler.
 4 #
 5 # The application 'guard' is installed as part of a gem, and
 6 # this file is here to facilitate running it.
 7 #
 8
 9 require 'pathname'
10 ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11   Pathname.new(__FILE__).realpath)
12
13 require 'rubygems'
14 require 'bundler/setup'
15
16 load Gem.bin_path('guard', 'guard')

Using binstubs, scripts can be executed directly from the bin directory.

1 $ bin/guard

1.2 Startup and Application Settings

Whenever you start a process to handle requests with Rails (such as with rails server), one of the first things that happens is that config/boot.rb is loaded.

There are three files involved in setting up the entire Rails stack:

config/boot.rb Sets up Bundler and load paths.

config/application.rb Loads Rails gems and gems for the specified Rails.env and configures the application.

config/environment.rb Runs all initializers.

All three are run when you need the whole Rails environment loaded. That’s what’s done by runner, console, server, and so on.

1.2.1 config/application.rb

The file config/application.rb is home to your Rails application settings, and it’s the only file required at the top of config/environment.rb.

Let’s go step by step through the settings provided in the default config/application.rb file that you’ll find in a newly created Rails application. By the way, as you’re reading the following sections, make a mental note to yourself that changes to these files require a server restart to take effect.

The next lines of config/application.rb are where the wheels really start turning once config/boot.rb is loaded:

require File.expand_path('../boot', __FILE__)

Note that the boot script is generated as part of your Rails application, but you won’t usually need to edit it.

Getting back to config/application.rb, we find the following line:

require 'rails/all'

You also have the ability to easily cherry-pick only the components needed by your application.

 1 # To pick the frameworks you want, remove 'require "rails/all"'.
 2 # and list the framework railties that you want:
 3 #
 4 # require "active_model/railtie"
 5 # require "active_record/railtie"
 6 # require "action_controller/railtie"
 7 # require "action_mailer/railtie"
 8 # require "action_view/railtie"
 9 # require "sprockets/railtie"
10 # require "rails/test_unit/railtie"

The main configuration of our application follows, which in Rails 4 gets its own module and class:

1 module TimeAndExpenses
2   class Application < Rails::Application
3     # Settings in config/environments/* take precedence over those
4     # specified here. Application configuration should go into files
5     # in config/initializers
6     # -- all .rb files in that directory are automatically loaded.

The creation of a module specifically for your application is part of the groundwork for supporting running multiple Rails applications in the same process.

1.2.1.1 Time Zones

The default time zone for Rails 4 applications is UTC (Coordinated Universal Time). If the business domain of your application is sensitive to knowing exactly what time zone the server is in, then you can use the following setting to override the default:

# Set Time.zone default to the specified zone and make Active Record
# autoconvert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names.
config.time_zone = 'Central Time (US & Canada)'


Juanito Says ...

rake time:zones:all will list all the time zones Rails knows about.


1.2.1.2 Localization

Rails features localization support via locale files and is covered in detail in Chapter 11, “All about Helpers,” in the TranslationHelper and I18n API sections.

The default locale is :en and can be overridden in your configuration.

# The default locale is :en and all translations from
# config/locales/*.rb,yml are autoloaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales',
#  '*.{rb,yml}')]
# config.i18n.default_locale = :de

1.2.1.3 Generator Default Settings

Rails generator scripts make certain assumptions about your tool chain. Setting the correct values here means having to type less parameters on the command line. For instance, to use RSpec without fixtures and Haml as the template engine, our settings would look like the following:

# Configure generator's values. Many other options are available.
# Be sure to check the documentation.
config.generators do |g|
  g.template_engine :haml
  g.test_framework :rspec, fixture: false
end

Note that RubyGems such as rspec-rails and factory_girl_rails handle this for you automatically.

1.2.2 Initializers

Rails 2 introduced the concept of breaking out configuration settings into their own small Ruby files under the config/initializers directory, where they are automatically loaded at startup. You can add configuration settings for your own application by adding Ruby files to the initializers directory. The following seven initializers are included by default in all Rails applications.

1.2.2.1 Backtrace Silencers

Nobody likes long exception backtraces, except maybe Java programmers. Rails has a mechanism for reducing the size of backtraces by eliminating lines that don’t really add anything to your debugging.

The backtrace_silencers.rb initializer lets you modify the way that backtraces are shortened. I’ve found it useful to remove backtrace entries for noisy libraries, but removing all silencers is usually never needed during normal application development.

1 # You can add backtrace silencers for libraries that you're using but
2 # don't wish to see in your backtraces.
3 Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
4
5 # You can also remove all the silencers if you're trying to debug a
6 # problem that might stem from framework code.
7 Rails.backtrace_cleaner.remove_silencers!

1.2.2.2 Filter Parameter Logging

When a request is made to your application, by default Rails logs details such as the request path, HTTP method, IP address, and parameters. If an attacker somehow gained access to your logs, they may be able to view sensitive information, like passwords and credit card numbers.

The filter_parameter_logging.rb initializer lets you specify which request parameters should be filtered from your log files. If Rails receives a request parameter included in the filter_parameters collection, it will mark it as [FILTERED] in your logs.

# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password]

1.2.2.3 Inflections

Rails has a class named Inflector whose responsibility is to transform strings (words) from singular to plural, class names to table names, modularized class names to ones without, class names to foreign keys, and so on. (Some of its operations have funny names, such as dasherize.)

The default inflections for pluralization and singularization of uncountable words are kept in an interesting file inside the Active Support gem, named inflections.rb.

Most of the time the Inflector class does a decent job of figuring out the pluralized table name for a given class, but occasionally it won’t. This is one of the first stumbling blocks for many new Rails users, but it is not necessary to panic. With a little ad hoc testing beforehand, it’s easy to find out how Inflector will react to certain words. We just need to use the Rails console, which by the way is one of the best things about working in Rails.

You fire up the console from your terminal with the rails console command.

$ rails console
>> ActiveSupport::Inflector.pluralize "project"
=> "projects"
>> ActiveSupport::Inflector.pluralize "virus"
=> "viri"
>> "pensum".pluralize  # Inflector features are mixed into String.
   by default
=> "pensums"

As you can see in the example, Inflector tries to be smart, pluralizing virus as viri; but if you know your Latin, you have already noticed that the plural pensum should actually be pensa. Needless to say, the inflector does not know Latin.7

7. Comically, the Rails inflection of virus is also wrong. See http://en.wikipedia.org/wiki/Plural_form_of_words_ending_in_-us#Virus

However, you can teach the inflector new tricks by adding new pattern rules, by pointing out an exception, or by declaring certain words unpluralizable. The preferred place to do that is inside the config/initializers/inflections.rb file, where a commented example is already provided:

1 ActiveSupport::Inflector.inflections(:en) do |inflect|
2   inflect.plural /^(ox)$/i, '1en'
3   inflect.singular /^(ox)en/i, '1'
4   inflect.irregular 'person', 'people'
5   inflect.uncountable %w( fish sheep )
6 end

The file activesupport/test/inflector_test_cases.rb8 has a long list of pluralizations correctly handled by Inflector. I found some of them pretty interesting, such as the following:

1 "datum"       => "data",
2 "medium"      => "media",
3 "analysis"    => "analyses"

8. https://github.com/rails/rails/blob/master/activesupport/test/inflector_test_cases.rb

1.2.2.4 Custom MIME Types

Rails supports a standard set of MIME types (*/*, text/html, text/plain, text/javascript, text/css, text/calendar, text/csv, application/xml, application/rss+xml, application/atom+xml, application/x-yaml, multipart/form-data, application/x-www-form-urlencoded, application/json).

Image

Table 1.1 Custom MIME Types

If your application needs to respond to other MIME types, you can register them in the mime_types.rb initializer:

# Add new MIME types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
# Mime::Type.register_alias "text/html", :iphone

1.2.2.5 Session Store

As of Rails 4, session cookies are encrypted by default using the new encrypted cookie store. The session_store.rb initializer configures the session store of the application by setting its session store type and key.

Rails.application.config.session_store :cookie_store,
  key: '_example_session'

The session cookies are signed using the secret_key_base set in the config/secrets.yml configuration file. If you are really paranoid, you can change the secret key in config/secrets.yml or run rake secret to generate a new one automatically.

1.2.2.6 Wrap Parameters

Introduced in Rails 3.1, the wrap_parameters.rb initializer configures your application to work with JavaScript MVC frameworks, such as Backbone.js, out of the box.

# Be sure to restart your server when you modify this file.

# This file contains settings for ActionController::ParamsWrapper,
# which is enabled by default.

# Enable parameter wrapping for JSON. You can disable this by setting
# :format to an empty array.
ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
end

# To enable root element in JSON for ActiveRecord objects.
# ActiveSupport.on_load(:active_record) do
#  self.include_root_in_json = true
# end

When submitting JavaScript object notation (JSON) parameters to a controller, Rails will wrap the parameters into a nested hash, with the controller’s name being set as the key. To illustrate, consider the following JSON:

{"title": "The Rails 4 Way"}

If a client submitted this JSON to a controller named ArticlesController, Rails would nest the params hash under the key “article.” This ensures the setting of model attributes from request parameters is consistent with the convention used when submitting from Rails form helpers.

{"title": "The Rails 4 Way", "article" => {"title": "The Rails 4 Way"}}

1.2.3 Additional Configuration

That does it for the configuration options for which we get examples in the default config/application.rb and the standard initializers. There are additional options that you can add in additional initializer files.

1.2.3.1 Load Path Modifications

By default, Rails looks for code in a number of standard directories, including all nested directories under app, such as app/models. This is referred to collectively as the load path. You can add other directories to the load path using the following code:

# Custom directories with classes and modules you want to be autoloadable
# config.autoload_paths += %W(#{config.root}/extras)

In case you didn’t know, the %W functions as a white space–delimited array literal and is used quite often in the Rails codebase for convenience.

1.2.3.2 Log-Level Override

The default log level is :debug, and you can override it if necessary.

# Force all environments to use the same logger level
# (by default production uses :info, the others :debug).
config.log_level = :debug

Use of the Rails logger is discussed in depth later on in this chapter.

1.2.3.3 Schema Dumper

Every time you run tests, Rails dumps the schema of your development database and copies it to the test database using an autogenerated schema.rb script. It looks very similar to an Active Record migration script; in fact, it uses the same API.

You might find it necessary to revert to the older style of dumping the schema using SQL if you’re doing things that are incompatible with the schema dumper code (see the comment).

# Use SQL instead of Active Record's schema dumper when creating the
# test database. This is necessary if your schema can't be completely
# dumped by the schema dumper—for example, if you have constraints
# or db-specific column types.
config.active_record.schema_format = :sql

Remember how we said that the value of the RAILS_ENV environment variable dictates which additional environment settings are loaded next? Let’s review the default settings for each of Rails’s standard modes.

1.2.3.4 Console

New to Rails 4 is the ability to supply a block to console, a method that is only evaluated when the Rails environment is loaded through the console. This allows you to set console-specific configurations, such as using Pry over IRB. Put this in your config/application.rb:

1 console do
2   # This block is called only when running console,
3   # so we can safely require pry here.
4   require "pry"
5   config.console = Pry
6 end

Note that the pry gem must be included in your Gemfile.

1.2.4 Spring Application Preloader

As of version 4.1, Rails ships with an application preloader named Spring.9 In doing so, during development, your application will remain running in the background. This speeds up development by eliminating the need to boot up Rails every time you execute tests or run a rake task.

9. https://github.com/rails/spring

While running, Spring monitors folders config and initializers for changes. If a file within those folders are changed, Spring will automatically restart your application. Spring will also restart if any gem dependencies are changed during development.

To demonstrate the speed increase Spring provides, let’s run the same rake task in both Rails 4.0 and a preloaded 4.1 application:

1 # Rails 4.0
2 $ time bin/rake about
3   ...
4   bin/rake about  1.20s user 0.36s system 22% cpu 6.845 total
5
6 # Rails 4.1
7 $ time bin/rake about
8   ...
9   bin/rake about  0.08s user 0.04s system 32% cpu 0.370 total

The preloaded Rails environment using Spring provided a savings of more than six seconds.

1.3 Development Mode

Development is Rails’s default mode and the one in which you will spend most of your time as a developer. This section contains an in-depth explanation of each setting.

# File: config/environments/development.rb
Rails.application.configure do
  # Settings specified here will take precedence over those in
  # config/application.rb.

1.3.1 Automatic Class Reloading

One of the signature benefits of using Rails is the quick feedback cycle whenever you’re working in development mode. Make changes to your code, hit Reload in the browser, and Shazam! Magically, the changes are reflected in your application. This behavior is governed by the config.cache_classes setting:

# In the development environment, your application's code is reloaded on
# every request. This slows down response time but is perfect for
# development since you don't have to restart the web server when you
# make code changes.
config.cache_classes = false

Without getting into too much nitty-gritty detail, when the config.cache_classes setting is true, Rails will use Ruby’s require statement to do its class loading, and when it is false, it will use load instead.

When you require a Ruby file, the interpreter executes and caches it. If the file is required again (as in subsequent requests), the interpreter ignores the require statement and moves on. When you load a Ruby file, the interpreter executes the file again, no matter how many times it has been loaded before.

Now it’s time to examine the Rails class-loading behavior a bit more in depth, because sometimes you won’t be able to get certain things to reload automatically, and it will drive you crazy unless you understand how class loading works!

1.3.1.1 The Rails Class Loader

In plain old Ruby, a script file doesn’t need to be named in any particular way that matches its contents. In Rails, however, you’ll notice that there’s almost always a direct correlation between the name of a Ruby file and the class or module contained within. Rails takes advantage of the fact that Ruby provides a callback mechanism for missing constants. When Rails encounters an undefined constant in the code, it uses a class loader routine based on file-naming conventions to find and require the needed Ruby script.

How does the class loader know where to search? We already covered it earlier in the chapter when we discussed the role of initializer.rb in the Rails startup process. Rails has the concept of load paths, and the default load paths include the base directories of just about anywhere you would think of adding code to your Rails application.

Want to see the contents of your project’s load path? Just fire up the console and type $LOAD_PATH:

$ rails console
Loading development environment.
>> $LOAD_PATH
=> ["/usr/local/lib/ruby/... # about 20 lines of output

I snipped the console output to save space. A typical Rails project load path will usually have 60 or more items in its load path. Try it and see.

1.3.1.2 Rails, Modules, and Autoloading Code

Normally in Ruby, when you want to include code from another file in your application, you have to include a require statement. However, Rails enhances Ruby’s default behavior by establishing a simple convention that enables Rails to automatically load your code in most cases. If you’ve used the Rails console at all, you’ve already seen this behavior in action: You never have to explicitly require anything!

This is how it works: If Rails encounters a class or module in your code that is not already defined, Rails uses the following convention to guess which files it should require to load that module or class.

If the class or module is not nested, insert an underscore between the constant’s names and require a file of this name. The following are some examples:

EstimationCalculator becomes require "estimation_calculator".

KittTurboBoost becomes require "kitt_turbo_boost".

If the class or module is nested, Rails inserts an underscore between each of the containing modules and requires a file in the corresponding set of subdirectories. The following are some examples:

MacGyver::SwissArmyKnife becomes require "mac_gyver/swiss_army_knife".

Example::ReallyRatherDeeply::NestedClass becomes require "example/really_rather_deeply/nested_class", and if not already loaded, Rails would expect to find it in a file called nested_class.rb in a directory called really_rather_deeply, itself in the directory example, which can be found somewhere in Ruby’s load path (e.g., one of the app subdirectories, lib, or a plugin’s lib directory).

The bottom line is that you should rarely need to explicitly load Ruby code in your Rails applications (using require) if you follow the naming conventions.

1.3.2 Eager Load

To speed up the boot time of starting a Rails server during development, code is no longer eager loaded. This behavior is governed by the config.eager_load setting:

# Do not eager load code on boot.
config.eager_load = false

In your production environment, you will want this set to true, as it copies most of your application in memory. This provides a performance increase to web servers that copy on write, such as Unicorn.

1.3.3 Error Reports

Requests from localhost, like when you’re developing, generate useful error messages that include debugging information such as a line number where the error occurred and a backtrace. Setting consider_all_requests_local to true causes Rails to display those developer-friendly error screens, even when the machine making the request is remote.

config.consider_all_requests_local = true

1.3.4 Caching

You normally do not want caching behavior when you’re in development mode. The only time you do want it is if you’re actually testing caching.

config.action_controller.perform_caching = true
# for testing in development mode

Remember to set it back to false when you’re done testing. Unexpected caching behavior can be very tricky to figure out.

1.3.5 Raise Delivery Errors

Rails assumes that you don’t want Action Mailer to raise delivery exceptions in development mode, so based on the config.action_mailer.raise_delivery_errors settings, it will swallow them. Mailing capabilities don’t necessarily work in an average development workstation, particularly on Windows and other platforms that lack sendmail.

# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false

If you actually want to send mail while in development mode as part of debugging or ad hoc testing, then you probably want to toggle this setting.


Xavier Says ...

I find it handy to set config.action_mailer.perform_deliveries = false in development. No delivery attempt is performed, but you can still see the mail in the log file to check that it looks good, copy account activation URLs, and so on.


1.3.6 Deprecation Notices

Deprecations warnings are very useful to let you know when you should stop using a particular piece of functionality. The configuration setting config.active_support.deprecation allows you to set how you would like to receive deprecation warnings. In development mode, by default all deprecation warnings will appear in the development log.

# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log

1.3.7 Pending Migrations Error Page

In previous versions of Rails, if pending migrations needed to be run, the web server would fail to start. As of Rails 4, a new error page is displayed instead, indicating to developers that they should run rake db:migrate RAILS_ENV=development to resolve the issue.

# Raise an error on page load if there are pending migrations
config.active_record.migration_error = :page_load

1.3.8 Assets Debug Mode

Rails 3.1 introduced us to the Asset Pipeline, a framework to concatenate and minify JavaScript and CSS assets. By default in development mode, JavaScript and CSS files are served separately in the order they were specified in their respective manifest files. Setting config.assets.debug to false would result in Sprockets concatenating and running preprocessors on all assets.

# Debug mode disables concatenation and preprocessing of assets.
config.assets.debug = true

The Asset Pipeline is covered in detailed in Chapter 20, “Asset Pipeline.”

1.4 Test Mode

Whenever you run Rails in test mode—that is, the value of the RAILS_ENV environment value is test—then the following settings are in effect (reproduced here for reference purposes):

 1 # File: config/environments/test.rb
 2 Rails.application.configure do
 3   # Settings specified here will take precedence over those in
 4   # config/application.rb.
 5
 6   # The test environment is used exclusively to run your application's
 7   # test suite. You never need to work with it otherwise. Remember that
 8   # your test database is "scratch space" for the test suite and is wiped
 9   # and recreated between test runs. Don't rely on the data there!
10   config.cache_classes = true
11
12   # Do not eager load code on boot. This avoids loading your whole
13   # application just for the purpose of running a single test. If you are
14   # using a tool that preloads Rails for running tests, you may have to set
15   # it to true.
16   config.eager_load = false
17
18   # Configure static asset server for tests with Cache-Control for
19   # performance.
20   config.serve_static_assets  = true
21   config.static_cache_control = "public, max-age=3600"
22
23   # Show full error reports and disable caching.
24   config.consider_all_requests_local       = true
25   config.action_controller.perform_caching = false
26
27   # Raise exceptions instead of rendering exception templates.
28   config.action_dispatch.show_exceptions = false
29
30   # Disable request forgery protection in test environment.
31   config.action_controller.allow_forgery_protection = false
32
33   # Tell Action Mailer not to deliver emails to the real world.
34   # The :test delivery method accumulates sent emails in the
35   # ActionMailer::Base.deliveries array.
36   config.action_mailer.delivery_method = :test
37
38   # Print deprecation notices to the stderr.
39   config.active_support.deprecation = :stderr
40 end

Most people get by without ever needing to modify their test environment settings.


Custom Environments

If necessary, you can create additional environments for your Rails app to run by cloning one of the existing environment files in the config/environments directory of your application. The most common use case for custom environments is in setting up additional production configurations, such as for staging and QA deployments. Do you have access to the production database from your development workstation? Then a triage environment might make sense. Use the normal environment settings for development mode, but point its database connection to a production database server. It’s a potentially lifesaving combination when you need to quickly diagnose issues in production.


1.5 Production Mode

Finally, production mode is what you want your Rails application running in whenever it is deployed to its hosting environment and serving public requests. There are a number of significant ways that production mode differs from the other modes, not least of which is the speed boost you get from not reloading all your application classes for every request.

 1 # File: config/environments/production.rb
 2 Rails.application.configure do
 3   # Settings specified here will take precedence over those in
 4   # config/application.rb.
 5
 6   # Code is not reloaded between requests.
 7   config.cache_classes = true
 8
 9   # Eager load code on boot. This eager loads most of Rails and
10   # your application in memory, allowing both thread web servers
11   # and those relying on copy on write to perform better.
12   # Rake tasks automatically ignore this option for performance.
13   config.eager_load = true
14
15   # Full error reports are disabled and caching is turned on.
16   config.consider_all_requests_local       = false
17   config.action_controller.perform_caching = true
18
19   # Enable Rack::Cache to put a simple HTTP cache in front of your
20   # application.
21   # Add `rack-cache` to your Gemfile before enabling this.
22   # For large-scale production use, consider using a caching reverse proxy
23   # like nginx, varnish, or squid.
24   # config.action_dispatch.rack_cache = true
25
26   # Disable Rails's static asset server (Apache or nginx will
27   # already do this).
28   config.serve_static_assets = false
29
30   # Compress JavaScripts and CSS.
31   config.assets.js_compressor  = :uglifier
32   # config.assets.css_compressor = :sass
33
34   # Whether to fallback to assets pipeline if a precompiled
35   # asset is missed.
36   config.assets.compile = false
37
38   # Generate digests for assets URLs.
39   config.assets.digest = true
40
41   # Version of your assets, change this if you want to expire
42   # all your assets.
43   config.assets.version = '1.0'
44
45   # Specifies the header that your server uses for sending files.
46   # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
47   # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
48   # for nginx
49
50   # Force all access to the app over SSL, use Strict-Transport-Security,
51   # and use secure cookies.
52   # config.force_ssl = true
53
54   # Set to :debug to see everything in the log.
55   config.log_level = :info
56
57   # Prepend all log lines with the following tags.
58   # config.log_tags = [ :subdomain, :uuid ]
59
60   # Use a different logger for distributed setups.
61   # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
62
63   # Use a different cache store in production.
64   # config.cache_store = :mem_cache_store
65
66   # Enable serving of images, stylesheets, and JavaScripts from an
67   # asset server.
68   # config.action_controller.asset_host = "http://assets.example.com"
69
70   # Precompile additional assets.
71   # application.js, application.css, and all non-JS/CSS in app/assets
72   # folder are already added.
73   # config.assets.precompile += %w( search.js )
74
75   # Ignore bad email addresses and do not raise email delivery errors.
76   # Set this to true and configure the email server for immediate delivery
77   # to raise delivery errors.
78   # config.action_mailer.raise_delivery_errors = false
79
80   # Enable locale fallbacks for I18n (makes lookups for any locale fall
81   # back to the I18n.default_locale when a translation cannot be found).
82   config.i18n.fallbacks = true
83
84   # Send deprecation notices to registered listeners.
85   config.active_support.deprecation = :notify
86
87   # Disable automatic flushing of the log to improve performance.
88   # config.autoflush_log = false
89
90   # Use default logging formatter so that PID and timestamp
91   # are not suppressed.
92   config.log_formatter = ::Logger::Formatter.new
93 end

1.5.1 Assets

In production mode, assets are by default precompiled by the Asset Pipeline. All files included in application.js and application.css asset manifests are compressed and concatenated into their respective files of the same name, located in the public/assets folder.

If an asset is requested that does not exist in the public/assets folder, Rails will throw an exception. To enable live asset compilation fallback on production, set config.assets.compile to true.

The application.js and application.css manifest files are the only JavaScript file and stylesheet included during the Asset Pipeline precompile step. To include additional assets, specify them using the config.assets.precompile configuration setting.

config.assets.precompile += %w( administration.css )

Like most features in Rails, the usage of the Asset Pipeline is completely optional. To include assets in your project as it was done in Rails 3.0, set config.assets.enabled to false.

1.5.2 Asset Hosts

By default, Rails links to assets on the current host in the public folder, but you can direct Rails to link to assets from a dedicated asset server. The config.action_controller.asset_host setting is covered in detail in Chapter 11, “All about Helpers,” in the “Using Asset Hosts” section.

1.6 Configuring a Database

The file database.yml found in the config folder specifies all the configuration settings required by Active Record to connect to a database. When a new application is generated, Rails automatically generates sections in the YAML for each environment.

The following is an example of a generated database.yml file configured to work with PostgreSQL.

 1 # config/database.yml
 2 default: &default
 3   adapter: postgresql
 4   encoding: unicode
 5   # For details on connection pooling, see rails configuration guide:
 6   # http://guides.rubyonrails.org/configuring.html#database-pooling
 7   pool: 5
 8   username: example
 9   password:
10
11 development:
12   <<: *default
13   database: example_development
14
15   # Connect on a TCP socket. Omitted by default since the client uses a
16   # domain socket that doesn't need configuration. Windows does not have
17   # domain sockets, so uncomment these lines.
18   #host: localhost
19
20   # The TCP port the server listens on. Defaults to 5432.
21   # If your server runs on a different port number, change accordingly.
22   #port: 5432
23
24   # Schema search path. The server defaults to $user,public
25   #schema_search_path: myapp,sharedapp,public.
26
27   # Minimum log levels, in increasing order:
28   #   debug5, debug4, debug3, debug2, debug1,
29   #   log, notice, warning, error, fatal, and panic.
30   # Defaults to warning.
31   #min_messages: notice
32
33 # Warning: The database defined as "test" will be erased and
34 # re-generated from your development database when you run "rake".
35 # Do not set this db to the same as development or production.
36 test:
37   <<: *default
38   database: example_test
39
40 production:
41   <<: *default
42   database: example_production

A common best practice within the Rails community has been not to store config/database.yml in version control. First and foremost, if a hacker gained access to the application repository, they would have all the connection settings to your production database. Second, developers on the team could potentially have different development and test database settings. New to Rails 4.1 is the ability to configure Active Record with an environment variable DATABASE_URL. This allows each developer working on the project to have her own copy of config/database.yml that is not stored in version control. The production environment of the Rails application would just need to have DATABASE_URL set with a valid connection string to be configured correctly.

1.7 Configuring Application Secrets

Being introduced in Rails 4.1 is the secrets.yml file found within the config folder. This file is meant to store your application’s sensitive data, such as access keys and passwords that are required for external APIs. At a minimum, Rails requires that secret_key_base is set for each environment of your application. In Rails 4.0, secret_key_base was set in the secret_token.rb initializer.

 1 # config/secrets.yml
 2
 3 # Be sure to restart your server when you modify this file.
 4
 5 # Your secret key is used for verifying the integrity of signed cookies.
 6 # If you change this key, all old signed cookies will become invalid!
 7
 8 # Make sure the secret is at least 30 characters and all random,
 9 # nonregular words or you'll be exposed to dictionary attacks.
10 # You can use `rake secret` to generate a secure secret key.
11
12 # Make sure the secrets in this file are kept private
13 # if you're sharing your code publicly.
14
15 development:
16   secret_key_base: 7aed4bcb28...
17
18 test:
19   secret_key_base: a4b717a2a8...
20
21 production:
22   secret_key_base: 39a63892bd...


Kevin Says ...

I would strongly advise to not store any production secret values in version control. Like database.yml, if a hacker gained access to the application repository, they could use these values to exploit your application. Instead, set all production secret values to environment variables. The environment variables will only be set on your production machine.

# config/secrets.yml
...
production:
  secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>

A hash of all the secrets defined in config/secrets.yml can be accessed via Rails.application.secrets.

>> Rails.application.secrets
=> {:secret_key_base=>"7aed4bcb28..."}
  To access a specific secrets, pass X to

An accessor for each secret key is also provided. For example, to access the secret for secret_key_base, invoke Rails.application.secrets.secret_key_base. This will return the value of secret_key_base for the current environment.

>> Rails.env
=> "development"
>> Rails.application.secrets.secret_key_base
=> "7aed4bcb28..."



Secret Token

Certain types of hacking involve modifying the contents of cookies without the server knowing about it. By digitally signing all cookies sent to the browser, Rails can detect whether they were tampered with. Rails signs cookies using the value of secret_key_base, found in config/secrets.yml, which is randomly generated along with your app.


1.8 Logging

Most programming contexts in Rails (models, controllers, view templates) have a logger attribute, which holds a reference to a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class. Can’t get a reference to logger somewhere in your code? The Rails.logger method references a logger that you can use anywhere.

It’s really easy to create a new Logger in Ruby, as shown in the following example:

 1 $ pry
 2 > require 'logger'
 3 => true
 4
 5 > logger = Logger.new STDOUT
 6 => #<Logger:0x00000106c795f0 @progname=nil, @level=0, ...>
 7
 8 > logger.warn "do not want!!!"
 9 W, [2013-11-02T18:34:30.281003 #54844]  WARN -- : do not want!!!
10 => true
11
12 > logger.info "in your logger, giving info"
13 I,[2013-11-02T18:34:57.186636 #54844]  INFO -- : in your logger, giving info
14 => true

Typically, you add a message to the log using the logger whenever the need arises, using a method corresponding to the severity of the log message. The standard logger’s severities are the following (in increasingly severe order):

Debug Use the debug level to capture data and application state useful for debugging problems later on. This level is not usually captured in production logs.

Info Use info level to capture informational messages. I like to use this log level for timestamping nonordinary events that are still within the bounds of good application behavior.

Warn Use the warn level to capture things that are out of the ordinary and might be worth investigating. Sometimes I’ll throw in a logged warning when guard clauses in my code keeps clients from doing something they weren’t supposed to do. My goal is to alert whoever’s maintaining the application about a malicious user or bug in the user interface, as in the following example:

 1 def create
 2   begin
 3     group.add_member(current_user)
 4     flash[:notice] = "Successfully joined #{scene.display_name}"
 5   rescue ActiveRecord::RecordInvalid
 6     flash[:error] = "You are already a member of #{group.name}"
 7     logger.warn "A user tried to join a group twice. UI should
 8                  not have allowed it."
 9   end
10
11   redirect_to :back
12 end

Error Use the error log level to capture information about error conditions that don’t require a server restart.

Fatal The worst case imaginable has happened—your application is now dead and manual intervention is necessary to restart it.

1.8.1 Rails Log Files

The log folder of your Rails application holds three log files corresponding to each of the standard environments. Log files can grow very large over time. A rake task is provided for easily clearing the log files:

$ rake log:clear  # Truncates all *.log files in log/ to zero bytes

The contents of log/development.log are very useful while you’re working. Many Rails coders leave a terminal window open with a continuous tail of the development log open while they’re coding:

$ tail -f log/development.log

  Article Load (0.2ms)  SELECT "articles".* FROM "articles" WHERE
    "articles"."id" = $1 LIMIT 1  [["id", "1"]]

All sorts of valuable information are available in the development log. For instance, every time you make a request, a bunch of useful information about it shows up in the log. Here’s a sample from one of my projects:

 1 Started GET "/user_photos/1" for 127.0.0.1 at 2007-06-06 17:43:13
 2   Processing by UserPhotosController#show as HTML
 3   Parameters: {"/users/8-Obie-Fernandez/photos/406"=>nil,
 4   "action"=>"show", "id"=>"406", "controller"=>"user_photos",
 5   "user_id"=>"8-Obie-Fernandez"}
 6   User Load (0.4ms)  SELECT * FROM users WHERE (users.'id' = 8)
 7   Photo Load (0.9ms)  SELECT * FROM photos WHERE (photos.'id' = 406
 8   AND (photos.resource_id = 8 AND photos.resource_type = 'User'))
 9   CACHE (0.0ms)   SELECT * FROM users WHERE (users.'id' = 8)
10 Rendered adsense/_medium_rectangle (1.5ms)
11   User Load (0.5ms)   SELECT * FROM users WHERE (users.'id' = 8)
12   LIMIT 1
13   SQL (0.4ms)   SELECT count(*) AS count_all FROM messages WHERE
14   (messages.receiver_id = 8 AND (messages.'read' = 0))
15 Rendered layouts/_header (25.3ms)
16 Rendered adsense/_leaderboard (0.4ms)
17 Rendered layouts/_footer (0.8ms)
18 Rendered photos/show.html.erb within layouts/application.html.erb (38.9ms)
19 Completed in 99ms (Views: 37.4ms | ActiveRecord: 12.3ms) with 200

This is a list of all the data items contained in that chunk of log output:

• Controller and action that were invoked

• Remote IP address of the computer making the request

• Timestamp indicating when the request happened

• Session ID associated with the request

• Hash of parameters associated with the request

• Database request information, including the time and the SQL statement executed

• Query cache hit info, including time and the SQL statement triggering results from the cache instead of a round trip to the database

• Rendering information for each template involved in rendering the view output and time consumed by each

• Total time used in completing the request with corresponding request-per-second figures

• Analysis of the time spent in database operations versus rendering

• HTTP status code and URL of the response sent back to the client

1.8.2 Tagged Logging

Log files can contain an extensive amount of information, making tracking down issues or particular requests difficult. To alleviate this issue, Rails 3.2 introduced the ability to prepend information to each of your log messages.

To add “tagged” information to your logs, pass an array of one or many method names that respond to the request object to the config.log_tags configuration setting.

To illustrate, assuming we want to track the subdomain that each request is made from, we can achieve this by setting config.log_tags to [:subdomain]. When Rails writes to the log, it will prefix the output of request.subdomain, resulting in a log message like the following:

[some_subdomain] Started GET "/articles" for 127.0.0.1 at 2013-02-01 11:49:09 -0500

1.8.3 Log File Analysis

A number of informal analyses can be easily performed using just the development log output and some common sense.

Performance One of the more obvious analyses would be a study of the performance of your application. The faster your requests execute, the more requests you can serve with a given Rails process. That’s why performance figures are often expressed in terms of requests per second. Find the queries and rendering sections that are taking a long time and figure out why.

It’s important to realize that the times reported by the logger are not accurate. In fact, they’re wrong more often than not, if simply for the reason that it’s very difficult to measure the timing of something from within itself. Add up the percentage of rendering and database times for any given request, and it will not always be close to 100 percent.

However, despite not being accurate in a purely objective sense, the reported times are perfect for making subjective comparisons within the same application. They give you a way of gauging whether an action is taking longer than it used to, whether it is relatively faster or slower than another action, and so on.

SQL Queries Active Record not behaving as expected? The fact that SQL generated by Active Record is logged can often help you debug problems caused by complicated queries.

Identification of N+1 Select Problems Whenever you are displaying a record along with an associated collection of records, there’s a chance that you will have a so-called N+1 select problem. You’ll recognize the problem by a series of many SELECT statements, with the only difference being the value of the primary key.

For example, here’s a snippet of some log output from a real Rails application showing an N+1 select issue in the way that FlickrPhoto instances are being loaded:

 1   FlickrPhoto Load (1.3ms)   SELECT * FROM flickr_photos WHERE
 2   (flickr_photos.resource_id = 15749 AND flickr_photos.resource_type =
 3   'Place' AND (flickr_photos.'profile' = 1)) ORDER BY updated_at desc
 4   LIMIT 1
 5   FlickrPhoto Load (1.7ms)   SELECT * FROM flickr_photos WHERE
 6   (flickr_photos.resource_id = 15785 AND flickr_photos.resource_type =
 7   'Place' AND (flickr_photos.'profile' = 1)) ORDER BY updated_at desc
 8   LIMIT 1
 9   FlickrPhoto Load (1.4ms)   SELECT * FROM flickr_photos WHERE
10   (flickr_photos.resource_id = 15831 AND flickr_photos.resource_type =
11   'Place' AND (flickr_photos.'profile' = 1)) ORDER BY updated_at desc
12   LIMIT 1

and so on, for pages and pages of log output. Look familiar?

Luckily, each of those database queries is executing very quickly (around 0.0015 seconds each). That’s because (1) MySQL is extraordinarily fast for small SELECT statements, and (2) my Rails process is on the same physical machine as the database.

Still, accumulate enough of those N queries and they add up quickly to eat away at performance. Absent the mitigating factors I mentioned, I would have a serious performance problem to address. The problem would be especially severe if the database was on a separate machine, giving me network latency to deal with on each of those queries.

N+1 select issues are not the end of the world. A lot of times all it takes is proper use of the includes method on a particular query to alleviate the problem.


Separation of Concerns

A well-designed MVC application follows certain protocols related to the logical tier that does database operations (that would be the model) versus rendering tasks (the view). Generally speaking, you want your controller to cause the loading of all the data that is going to be needed for rendering from the database. In Rails, this is accomplished by controller code that queries the model for needed data and makes that data available to the view.


Database access during rendering is usually considered a bad practice. Calling database methods directly from template code violates proper separation of concerns and is a maintainability nightmare.10

10. Practically every PHP application ever written has this problem.

However, there are plenty of opportunities for implicit database access during view rendering to creep into your codebase, encapsulated by the model and perhaps triggered by lazy loading of associations. Can we conclusively call it a bad practice? It’s hard to say so definitively. There are cases (such as usage of fragment caching) where it makes sense to have database operations happening during view rendering.


Using Alternate Logging Schemes

It’s easy! Just assign a class compatible with Ruby’s Logger to one of the various logger class variables, such as ActiveRecord::Base.logger. A quick hack based on the ability to swap loggers is one demonstrated by David at various events, including his keynote at Railsconf 2007. During a console session, assign a new Logger instance pointing to STDOUT to ActiveRecord::Base.logger in order to see the SQL being generated right in your console. Jamis has a complete write-up of the technique and more at http://weblog.jamisbuck.org/2007/1/31/more-on-watching-activerecord.


1.8.3.1 Rails::Subscriber.colorize_logging

This code tells Rails whether to use ANSI codes to colorize the logging statements. The colors make it much easier to read the logs (except on Windows) and may complicate matters if you use software like syslog. It defaults to true. Change to false if you view your logs with software that doesn’t understand the ANSI color codes.

Here’s a snippet of log output with the ANSI codes visible:

1 ^[[4;36;1mSQL (0.0ms)^[[0m   ^[[0;1mMysql::Error: Unknown table
2 'expense_reports': DROP TABLE expense_reports^[[0m
3   ^[[4;35;1mSQL (3.2ms)^[[0m   ^[[0mCREATE TABLE expense_reports ('id'
4 int(11) DEFAULT NULL auto_increment PRIMARY KEY, 'user_id' int(11))


Wilson Says ...

Almost nobody I meet seems to know how to display colorized logs in a pager. The -R option tells less to output “raw” control characters to the screen.



Syslog

UNIX-like systems have a system service called syslog. For various reasons, it might be a better choice for production logging of your Rails applications.

• Finer-grained control over logging levels and content is offered.

• Consolidation of logger output for multiple Rails applications is possible.

• If you’re using remote syslog capabilities of many systems, consolidation of logger output for multiple Rails application servers is possible. Contrast with having to handle individual log files on each application server box separately.

You can use Eric Hodel’s SyslogLogger11 to interface your Rails application to syslog.

11. http://docs.seattlerb.org/SyslogLogger/


1.9 Conclusion

We’ve kicked off our Rails journey by covering Bundler in fairly good detail and then reviewing the different environments in which Rails executes and how it loads its dependencies, including your application code. An in-depth look at config/application.rb and its per-mode variants revealed how we can customize Rails behavior to our taste.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.160.181