Configuring Your Dancer Applications

It's been a really exciting year for Dancer2 (and an even more exciting two years since the last Advent calendar!), and one of the many things that's been improved is the configuration of Dancer2 applications. While some configuration oddities have been addressed, some additional conveniences have been added as well. Let's get started and explore what's changed!

The Basics

Let's assume you are building an application that is contained in a directory named appdir/. The easiest way to configure the application there is with a simple config.yml:

appname: mytestapp

plugins:
    Debugger:
        enabled: 1
    Auth::Tiny:
        login_route: '/auth/login'

You are not limited to YAML, however. JSON works just as well:

{
    "appname": "mytestapp",
    "plugins": {
        "Debugger": {
             "enabled": 1
        },
        "Auth::Tiny": {
            "login_route": "/auth/login"
        }
    }
}

In fact, any file format that can be read by Config::Any can be used for your application's config file. TIMTOWTDI!

Note: The examples that follow assume a YAML file format, but rest assured that these same techniques work with any configuration file format supported by Dancer2.

Some Potential Problems

In Dancer1, YAML was the only supported format, and as such, establishing a set order in which configuration files were read was pretty easy: config.yml followed by environments/$environment_name.yml. Since Dancer2 supports multiple file formats, the configuration file loader looks for all files whose name starts with config and merges the results together, and the order in which they are merged is dependent upon the order in which Config::Any tells us what file types it supports. This is not ideal because there is no reliable order in which our configuration files are read - there is no guarantee that config.yml is read before config.json... That's pretty scary in a production environment!

To resolve this potential gotcha, set the DANCER_CONFIG_EXT environment variable to the file extension that you wish to use for your configuration files. For example:

DANCER_CONFIG_EXT=json

If this variable is set, no other type of configuration file will be read, only JSON files. Dancer2 will be nice and let you know if there are other configuration files of other formats present, however.

Creating Local Overrides

Sometimes you will have local overrides for or additions to certain settings found in your config.yml file, such as database settings, that you do not want to commit to your version control system. Thankfully, Dancer2 accounts this by letting you add a file called config_local.yml. Local configuration files are always processed after the files they are named for; that is to say that config.yml is always processed first, followed by config_local.yml.

So let's say that your config.yml is the one above, and your config_local.yml contains this:

DBIC:
    default:
        dsn: dbi:Pg:dbname=my_db
        schema_class: My::Schema
        user: dbuser
        password: dbpass
        options:
            RaiseError: 1
            PrintError: 1

Effectively, your running configuration would be this:

appname: mytestapp

plugins:
    Debugger:
        enabled: 1
    Auth::Tiny:
        login_route: '/auth/login'
    DBIC:
        default:
            dsn: dbi:Pg:dbname=my_db
            schema_class: My::Schema
            user: dbuser
            password: dbpass
            options:
                RaiseError: 1
                PrintError: 1

If you've converted to Dancer2 from Catalyst, this configuration technique should be familiar to you.

Configuring for Multiple Deployment Environments

In reality, your local development settings will likely differ from shared development server settings, which will likely be different than staging or production environment settings. To help you with this, Dancer2 lets you specify your runtime environment when running your application:

DANCER_ENVIRONMENT=staging plackup bin/mytestapp.psgi

This tells Dancer2 to load environments/staging.yml after config.yml and, if it exists, config_local.yml.

As with the previous example, the configuration files are merged in order, with settings in environments/staging.yml taking precedence over all others. If you had a environments/staging_local.yml file, it would get read and merged after all other files.

One Final Example: Read All the Files!

If you are using YAML-based configuration files only, and are launching an application in a production environment, these settings:

DANCER_CONFIG_EXT=yml
DANCER_ENVIRONMENT=production

will read the following files (for sake of illustration, let's assume you use every one of these files):

appdir/config.yml
appdir/config_local.yml
appdir/environments/production.yml
appdir/environments/production_local.yml

Settings found in the last file merged always takes precedence, followed by settings found in the next most recently read file, and so on.

Debugging Configuration Issues

If you are ever unsure what order configuration files are being processed in, setting the environment variable DANCER_CONFIG_VERBOSE=1 prior to launching your application will show you the order in which files have been loaded.

Wrapping Up

Dancer2 developers gained a lot of flexibility in how to to configure their applications in 2016. The core team would like to give a shout-out to Jonathan Scott Duff (aka perlpilot) for his work in making this possible.

Author

This article has been written by Jason A. Crome (CromeDome) cromedome@cpan.org for the Perl Dancer Advent Calendar 2016.

Copyright

No copyright retained. Enjoy.