# Anyway Config turns a gem's settings into a Ruby class with defaults, loaders and tests

> Anyway Config is a Ruby configuration library that replaces scattered environment lookups with configuration classes that declare their parameters, then loads values from YAML, credentials and environment variables through a pipeline of loaders. It suits gem authors who want a better setup experience for their users without writing an initializer for every option.

**palkan/anyway_config** — Configuration library for Ruby gems and applications

- Repository: https://github.com/palkan/anyway_config
- Stars: 923 · Forks: 62
- Language: Ruby
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/palkan-anyway-config

## Configuration classes instead of environment lookups scattered through code

Anyway Config is described as a configuration library for Ruby gems and applications, and its tagline is one configuration to rule all data sources. The core idea is that it abstracts the configuration layer by introducing configuration classes that describe available parameters and their defaults. The README makes the case in two directions. For library authors, the benefit is a better UX for end users, with zero-code configuration so there are no more boilerplate initializers, and per-environment and local settings support out of the box. For application developers, the benefit is keeping configuration organized through named configs instead of a bloated .env or settings.yml, and freeing application code of a dependency on ENV, credentials or secrets, because your code should not rely on configuration data sources. The primary language is Ruby, and the topics list configuration, rails and hacktoberfest.

## attr_config declares parameters, defaults and accessors

The DSL is small. A class inherits from Anyway::Config and calls attr_config to declare parameters with their defaults:

```ruby
require "anyway_config"

module MyCoolGem
  class Config < Anyway::Config
    attr_config user: "root", password: "root", host: "localhost"
  end
end
```

attr_config creates the accessors and populates the default values, and a parameter can be declared without a default if you write attr_config :user, :password, host: "localhost", options: {}. You then instantiate the class and read the values: MyCoolGem::Config.new.user returns "root". Two conveniences are built in. Boolean attributes with a false or true default automatically get a matching predicate method, so a debug: false attribute yields a debug? accessor. And it is safe to use non-primitive defaults such as Hashes or Arrays, because the values are deeply duplicated for each config instance, so one instance mutating a default hash cannot affect another.

## A loader pipeline pulls values from YAML, credentials and ENV

The gem takes care of loading parameters from different sources, and the internal design is a pipeline pattern with a Loaders API to manage and extend that functionality. That is the mechanism that makes the library worth the dependency. The README's own table of contents lists the loader-related features it documents further down, among them data loaders with a Doppler integration, EJSON support and custom loaders, plus a section on environment variables, type coercion, local configuration and source tracing. The pipeline shape explains why local and per-environment overrides work the same way as the primary sources: each loader contributes values, and the classes you declared decide which keys are meaningful and what they default to. The documentation also lists a section on pattern matching, which suggests the configuration object can be matched against rather than only queried attribute by attribute.

## The 2.0 accessor change breaks instance variable overrides

There is one upgrade hazard that is documented precisely, and it will bite anyone who wrote a custom reader before the 2.0 release. Since v2.0 the accessors created by attr_config are not attr_accessor, meaning they do not populate instance variables. Code that overrode a reader by writing to an instance variable no longer works, and the README says you must switch to using super or the values store:

```ruby
class MyConfig < Anyway::Config
  attr_config :host, :port, :url, :meta

  # override writer to handle type coercion
  def meta=(val)
    super(JSON.parse(val))
  end

  # or override reader to handle missing values
  def url
    super || (self.url = "#{host}:#{port}")
  end
end
```

The same note recommends supporting both v1.x and v2.0 in your gem for the time being, using a feature check on the class method added in 2.0, .on_load, so the same library works with an old version of the gem installed. The README also flags that until v2.1 it will still be possible to read instance variables, so the instance variable style is on its way out rather than already gone.

## Installation is a gemspec dependency or a Gemfile line

There are two documented routes, one for gem authors and one for application developers. A gem declares it in the specification:

```ruby
# my-cool-gem.gemspec
Gem::Specification.new do |spec|
  # ...
  spec.add_dependency "anyway_config", ">= 2.0.0"
  # ...
end
```

and an application adds it to its bundle:

```ruby
# Gemfile
gem "anyway_config", "~> 2.0"
```

The supported Ruby versions are listed plainly, Ruby on MRI at 2.7.0 or newer, and JRuby at 9.3.0 or newer. The README also notes that it documents the 2.x version, and that for version 1.x you should look at the 1-4-stable branch, which is where you would find the older behaviour if you need to compare. The project was built by Evil Martians, and the README links their write-up on keeping Ruby configuration sane.

## Rails integration is a documented chapter of the README

The README spends a whole section on Rails, and it is worth knowing what it covers before you choose the library. It documents data population, organizing configs, and generators, which together are the answer to the question of how a Rails app feeds its own configuration classes. It also has a separate section for using the library with Ruby applications, so the two host styles are treated differently rather than the Rails path being assumed. The same table of contents lists a section on validation and callbacks under Usage, and one on dynamic configuration, both of which are mechanisms a class based approach can offer that a plain hash cannot: a schema with validations attached, and configuration values that are computed rather than loaded.

## The toolchain around the gem shows how it is maintained

The repository is laid out like a well kept gem, and the tooling tells you how much work goes into it. It carries a Steepfile and a sig/ directory plus an rbs_collection.yaml, so the library ships type signatures and is checked with Steep, and the table of contents has a section on RBS support. Linting is handled by RuboCop with a .rubocop.yml and a .rubocop/ directory, plus a .rubocop-md.yml for the Markdown, and the Makefile separates lint from test and release, with release depending on both. The test target runs the suite twice, once locally and once with CI=true set, and the release target uses gem release -t. Two smaller signals are worth noting: .gem_release.yml governs the gem release metadata, and the gemfiles/ directory exists for testing against multiple dependency sets. The last push was on 2026-07-25, the repository is not archived, and the newest release is v2.8.0 from 2026-01-28.

## Conclusion

Anyway Config suits gem authors who want their users to configure things with zero-code setup and who need the resulting configuration to be testable, and it suits application developers who want named configuration classes instead of a bag of environment variables. It does not suit a project that needs its configuration read at arbitrary times from arbitrary places, because the library is built around a class you instantiate, and it does not suit a team that has not decided who owns defaults, since the defaults live in your source and every value can be overridden by a loader. Before you upgrade past 2.0, note that accessors created by attr_config are no longer attr_accessor, so any reader you overrode through an instance variable must move to super or the values store.

## FAQ

### What does Anyway Config do?

It is a configuration library for Ruby gems and applications that introduces configuration classes describing available parameters and their defaults, and loads values from different sources such as YAML, credentials and environment variables through a pipeline of loaders.

### How do I add Anyway Config to my Ruby project?

In a Gemfile use gem "anyway_config", "~> 2.0". In a gemspec use spec.add_dependency "anyway_config", ">= 2.0.0". Supported versions are Ruby MRI >= 2.7.0 and JRuby >= 9.3.0.

### What changed in Anyway Config 2.0?

Since v2.0 the accessors created by attr_config are not attr_accessor, so they do not populate instance variables. Code that overrode readers through instance variables must switch to using super or the values store.

### How do I declare configuration parameters in Anyway Config?

Subclass Anyway::Config and call attr_config with the parameter names and defaults, for example attr_config user: "root", password: "root", host: "localhost". It creates the accessors and populates the default values.

### Is it safe to use Hash or Array defaults in Anyway Config?

Yes. The documentation states that non-primitive default values are safe to use, because the values are deeply duplicated for each config instance.

## Sources

- [Issues](https://github.com/palkan/anyway_config/issues)
- [License: MIT](https://github.com/palkan/anyway_config/blob/master/LICENSE)
- [palkan/anyway_config on GitHub](https://github.com/palkan/anyway_config)
- [README](https://github.com/palkan/anyway_config/blob/master/README.md)
- [Releases](https://github.com/palkan/anyway_config/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/palkan-anyway-config
