<commit_before># Levels

[![Build Status](https://secure.travis-ci.org/rcarver/levels.png)](http://travis-ci.org/rcarver/levels)

Levels is a tool for reading and writing configuration data. A level is
a set of key/value pairs containing configuration data. Multiple levels
may be merged in a predictable, useful way.

  > **KRAMER:** *I'm completely changing the configuration of the apartment. You're not gonna believe it when you see it. A whole new lifestyle.*

  > **JERRY:** *What are you doing?*

  > **KRAMER:** *Levels.*

## Creating a level

Each level of configuration is made up of one or more groups. Each group
is a set of key/value pairs. To describe a very simple web application
made up of a server and a task queue, you could write this (in JSON).

```json
{
  "server": {
    "hostname": "example.com"
  },
  "task_queue": {
    "workers": 5,
    "queues": ["high", "low"]
  }
}
```

Now consider having a common "base" configuration, with
slight differences in development and production. Our base
configuration defines the possible keys, with default values.

A "production" level could override the relevant values like this.

```json
{
  "server": {
    "hostname": "example.com"
  },
  "task_queue": {
    "workers": 5
  }
}
```

The system's environment is another level. To alter any value at
runtime, follow a convention to set the appropriate environment
variable.

```bash
TASK_QUEUE_WORKERS="10"
```

### Writing a configuration

Levels may be written in several formats.

  * **RUBY** is the most common and powerful for hand written configs.
  * **JSON** is convenient for machine generated configs.
  * **Environment Variables** are useful for local or runtime
    configuration. This syntax may not be used for the "base" level.

#### Data Types

Levels has a limited understanding of data types by design. The guiding
principles for this are:

  * It must be possible to represent any value in an environment
    variable.
  * Use only types that are native in JSON.

Therefore, Levels only supports the following types:

  * **string** (Ruby `String`)
  * **integer** (Ruby `Fixnum`)
  * **float** (Ruby `Float`)
  * **boolean** (Ruby `TrueClass` or `FalseClass`)
  * **array** (Ruby `Array`) of values, which are also typed.
  * **null** (Ruby `NilClass`)

Notice that JSON's Object is not supported. This is because groups are
objects, so key/values pairs are already available. As well, it's
difficult to represent key/value pairs in an environment variable.

Fortunately, these simple types are perfectly adequate for the purposes
of system configuration.

#### Ruby Syntax

The Ruby DSL is a clean, simple format. It aims to be very readable and
writable. It is also extensible.

The format looks like this:

```ruby
set :server,
    hostname: "example.com"

set :task_queue,
    workers: 5,
    queues: ["high", "low"]
```

The Ruby syntax supports **computed values**.

```ruby
configure :task_queue,
  queues: -> { [server.hostname, "high", "low"] }
```

#### JSON Syntax

JSON syntax is straightforward. Because the datatypes supported by
Levels are the same as supported by JSON, there's nothing else you need
to know.

```json
{
  "server": {
    "hostname": "example.com"
  },
  "task_queue": {
    "workers": 5,
    "queues": ["high", "low"]
  }<commit_msg>update the ruby example in README<commit_after># Levels

[![Build Status](https://secure.travis-ci.org/rcarver/levels.png)](http://travis-ci.org/rcarver/levels)

Levels is a tool for reading and writing configuration data. A level is
a set of key/value pairs containing configuration data. Multiple levels
may be merged in a predictable, useful way.

  > **KRAMER:** *I'm completely changing the configuration of the apartment. You're not gonna believe it when you see it. A whole new lifestyle.*

  > **JERRY:** *What are you doing?*

  > **KRAMER:** *Levels.*

## Creating a level

Each level of configuration is made up of one or more groups. Each group
is a set of key/value pairs. To describe a very simple web application
made up of a server and a task queue, you could write this (in JSON).

```json
{
  "server": {
    "hostname": "example.com"
  },
  "task_queue": {
    "workers": 5,
    "queues": ["high", "low"]
  }
}
```

Now consider having a common "base" configuration, with
slight differences in development and production. Our base
configuration defines the possible keys, with default values.

A "production" level could override the relevant values like this.

```json
{
  "server": {
    "hostname": "example.com"
  },
  "task_queue": {
    "workers": 5
  }
}
```

The system's environment is another level. To alter any value at
runtime, follow a convention to set the appropriate environment
variable.

```bash
TASK_QUEUE_WORKERS="10"
```

### Writing a configuration

Levels may be written in several formats.

  * **RUBY** is the most common and powerful for hand written configs.
  * **JSON** is convenient for machine generated configs.
  * **Environment Variables** are useful for local or runtime
    configuration. This syntax may not be used for the "base" level.

#### Data Types

Levels has a limited understanding of data types by design. The guiding
principles for this are:

  * It must be possible to represent any value in an environment
    variable.
  * Use only types that are native in JSON.

Therefore, Levels only supports the following types:

  * **string** (Ruby `String`)
  * **integer** (Ruby `Fixnum`)
  * **float** (Ruby `Float`)
  * **boolean** (Ruby `TrueClass` or `FalseClass`)
  * **array** (Ruby `Array`) of values, which are also typed.
  * **null** (Ruby `NilClass`)

Notice that JSON's Object is not supported. This is because groups are
objects, so key/values pairs are already available. As well, it's
difficult to represent key/value pairs in an environment variable.

Fortunately, these simple types are perfectly adequate for the purposes
of system configuration.

#### Ruby Syntax

The Ruby DSL is a clean, simple format. It aims to be readable, writable and
editable. It is also extensible.

The format looks like this:

```ruby
group :server
  set hostname: "example.com"

group :task_queue
  set workers: 5
  set queues: ["high", "low"]
```

The Ruby syntax supports **computed values**.

```ruby
group :task_queue
  set queues: -> { [server.hostname, "high", "low"] }
```

#### JSON Syntax

JSON syntax is straightforward. Because the datatypes supported by
Levels are the same as supported by JSON, there's nothing else you need
to know.

```json
{
  "server": {
    "hostname": "example.com"
  },
  "task_queue": {
    "workers": 5,
    "queues": ["high", "low"]
  }
{'fraction_non_alphanumeric': 0.11154598825831702, 'fraction_numerical': 0.0018064127653168748, 'mean_word_length': 3.9214814814814813, 'pattern_counts': {'":': 28, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2028327', 'n_tokens_mistral': 2026, 'n_tokens_neox': 1899, 'n_words': 877}