Test Your Rails Application Configuration

A Rails application has many configuration options. Learn how to test one of them.

Why?

Well, what are the consequences of an improperly configurated application? Poor performance? Loss of revenue? Litigation? None of these consequences is desirable. We can avoid them by configuring an application correctly. And, we can be confident that it will stay that way by running examples of correct behavior against the configuration every time it's changed.

Exploring the Configuration

Rails application configuration is primarily exposed in config/application.rb via an Application class. [1] Here's an elided example.

config/application.rb
  ...
  module Foo
    class Application < Rails::Application
      ...
      # Configure sensitive parameters which will be filtered from the log file.
      config.filter_parameters += [:password]
      ...
    end
  end
  

The application configuration can also be explored in the console, as shown below. Using pry is optional. [2].

  $ rails c
  Loading development environment (Rails 3.2.3)
  1.9.3p125 :001 > pry
  [1] pry(main)> Foo::Application.config
  => #<Rails::Application::Configuration:0x007ff93bc52010
    ...
    @filter_parameters=[:password],
    @force_ssl=false,
    ...
    @time_zone="Central Time (US & Canada)",
    ...
  

Testing the Configuration

I've highlighted the filter_parameters option in the file and the console. It informs the application to censor the listed request parameters from logs. Rails filters :password by default. Let's write an example that proves :password and :social_security_number will be filtered.

In an editor, create a new file named spec/config/application_spec.rb, and write the following two examples.

spec/config/application_spec.rb
  require 'spec_helper'

  describe Portal::Application, 'configuration' do
    let(:config) { described_class.config }

    [:password, :social_security_number].each do |param|
      it "filters #{param.inspect} from logs" do
        config.filter_parameters.should include(param)
      end
    end
  end
  

Run the examples, specifying the "documentation" format for output. [3]

  $ rspec spec/config/application_spec.rb --format documentation

  Foo::Application configuration
    filters :password from logs
    filters :social_security_number from logs (FAILED - 1)

  Failures:

    1) Foo::Application configuration filters :social_security_number from logs
       Failure/Error: config.filter_parameters.should include(param)
         expected [:password] to include :social_security_number
         Diff:
         @@ -1,2 +1,2 @@
         -[:social_security_number]
         +[:password]
       # ./spec/config/application_spec.rb:8:in `block (3 levels) in <top (required)>'

  Finished in 0.00428 seconds
  2 examples, 1 failures

  Failed examples:

  rspec ./spec/config/application_spec.rb:7 # Foo::Application configuration filters :social_security_number from logs
  

Perfect. We have one passing example for :password, and we have one failing example that indicates exactly what we need to do to correct our configuration.

Open config/application.rb in an editor and find the filter_paramters option.

config/application.rb
  ...
  module Foo
    class Application < Rails::Application
      ...
      # Configure sensitive parameters which will be filtered from the log file.
      config.filter_parameters += [:password]
      ...
    end
  end
  

To satisfy the failing examples, add :social_security_number to filter_parameters.

config/application.rb
  ...
  module Foo
    class Application < Rails::Application
      ...
      # Configure sensitive parameters which will be filtered from the log file.
      config.filter_parameters += [:password, :social_security_number]
      ...
    end
  end
  

Rerun the examples. filter_parameters is set as desired.

  $ rspec spec/config/application_spec.rb --format documentation

  Foo::Application configuration
    filters :password from logs
    filters :social_security_number from logs

  Finished in 0.00339 seconds
  2 examples, 0 failures
  

Conclusion

A Rails applicaton exposes its configuration via an Application class. We can easily and simply test that the configuration is what we want it to be and that it remains that way. Thus, we can mitigate the risks, some severe, of an improperly configured application.

Notes

[1] Environment-specific configuration can be set in files in config/environments.

[2] Here, pry is useful for its much nicer format than the default. It's so much more than that, though. I highly recommend adding it to your toolset. It vastly expands your capabilities to interact with Ruby code.

[3] The --format documentation option commands RSpec to display examples grouped and nested under their descriptions. Run rspec --help for more information. If you find a set of options that you always want to use, you can add them to a .rspec file in your home directory. See read command line configuration options from files.

Craig Demyanovich, Software Craftsman

Craig Demyanovich is an avid hockey player and loves visiting new places with his wife Sandy.