用于 Ruby 宝石和应用程序的配置库
One configuration to rule all data sources
Anyway Config is a configuration library for Ruby gems and applications.
As a library author, you can benefit from using Anyway Config by providing a better UX for your end-users:
For application developers, Anyway Config could be useful to:
.env/settings.yml/whatever.NOTE: this readme shows documentation for 2.x version. For version 1.x see the 1-4-stable branch.
Anyway Config is built by Evil Martians, an American design and engineering consultancy for developer tools, AI, and cybersecurity startups.
Anyway Config abstractize the configuration layer by introducing configuration classes which describe available parameters and their defaults. For example:
module Influxer
class Config = 2.0.0"
# ...
end
Or adding to your project:
# Gemfile
gem "anyway_config", "~> 2.0"
Using configuration classes allows you to make configuration data a bit more than a bag of values: you can define a schema for your configuration, provide defaults, add validations and additional helper methods.
Anyway Config provides a base class to inherit from with a few DSL methods:
require "anyway_config"
module MyCoolGem
class Config "root"
Bonus:: if you define attributes with boolean default values (false or true), Anyway Config would automatically add a corresponding predicate method. For example:
attr_config :user, :password, debug: false
MyCoolGem::Config.new.debug? #=> false
MyCoolGem::Config.new(debug: true).debug? #=> true
NOTE: since v2.0 accessors created by attr_config are not attr_accessor, i.e. they do not populate instance variables. If you used instance variables before to override readers, you must switch to using super or values store:
class MyConfig ::Config` then use the module name (`SomeModule::Config => "somemodule"`)
- if the class name has a form of `Config` then use the class name prefix (`SomeConfig => "some"`)
**NOTE:** in both cases, the config name is a **downcased** module/class prefix, not underscored.
You can also specify the config name explicitly (it's required in cases when your class name doesn't match any of the patterns above):
```ruby
module MyCoolGem
class Config 42
# you can specify the config file path or env prefix
config = Anyway::Config.for(:my_app, config_path: "my_config.yml", env_prefix: "MYAPP")
…
ruby
class MyConfig raises Anyway::Config::ValidationError
…
ruby
class EnvConfig = 6.0; for older versions use version 1.x of the gem.
We recommend going through [Data population](#data-population) and [Organizing configs](#organizing-configs) sections first,
and then use [Rails generators](#generators) to make your application Anyway Config-ready.
### Data population
Your config is filled up with values from the following sources (ordered by priority from low to high):
1) **YAML configuration files**: `RAILS_ROOT/config/my_cool_gem.yml`.
Rails environment is used as the namespace (required); supports `ERB`:
```yml
test:
host: localhost
port: 3002
development:
host: localhost
port: 3000
NOTE: You can override the environment name for configuration files via the ANYWAY_ENV environment variable or by setting it explicitly in the code: Anyway::Settings.current_environment = "some_other_env".
You can also configure additional Ruby classes that you want to deserialized from YAML (permitted_classes option). For example:
Anyway::Loaders::YAML.permitted_classes (name) { Rails.root.join("data", "configs", "#{name}.yml") }
_CONF env variable, e.g., MYCOOLGEM_CONF=path/to/cool.yml—creates a named configuration class and optionally the corresponding YAML file; creates application_config.rb` is missing.The generator command for the Heroku example above would be:
$ rails g anyway:config heroku app_id app_name dyno_id release_version slug_commit
generate anyway:install
rails generate anyway:install
create config/configs/application_config.rb
append .gitignore
create config/configs/heroku_config.rb
Would you like to generate a heroku.yml file? (Y/n) n
You can also specify the --app option to put the newly created class into app/configs folder.
Alternatively, you can call rails g anyway:app_config name param1 param2 ....
NOTE: The generated ApplicationConfig class uses a singleton pattern along with delegate_missing_to to re-use the same instance across the application. However, the delegation can lead to unexpected behaviour and break Anyway Config internals if you have attributes named as Anyway::Config class methods. See #120.
Anyway Config activates Rails-specific features automatically on the gem load only if Rails has been already required (we check for the Rails::VERSION constant presence). However, in some cases you may want to use Anyway Config before Rails initialization (e.g., in config/puma.rb when starting a Puma web server).
By default, Anyway Config sets up a hook (via TracePoint API) and waits for Rails to be loaded to require the Rails extensions (require "anyway/rails"). In case you load Rails after Anyway Config, you will see a warning telling you about that. Note that config classes loaded before Rails are not populated from Rails-specific data sources (e.g., credentials).
You can disable the warning by setting Anyway::Rails.disable_postponed_load_warning = true in your application. Also, you can disable the hook completely by calling Anyway::Rails.tracer.disable.
The default data loading mechanism for non-Rails applications is the following (ordered by priority from low to high):
./config/.yml.In pure Ruby apps, we also can load data under specific environments (test, development, production, etc.).
If you want to enable this feature you must specify Anyway::Settings.current_environment variable for load config under specific environment.
Anyway::Settings.current_environment = "development"
You can also specify the ANYWAY_ENV=development environment variable to set the current environment for configuration.
YAML files should be in this format:
development:
host: localhost
port: 3000
If Anyway::Settings.current_environment is missed we assume that the YAML contains values for a single environment:
host: localhost
port: 3000
ERB is supported if erb is loaded (thus, you need to call require "erb" somewhere before loading configuration).
You can specify the lookup path for YAML files in one of the following ways:
Anyway::Settings.default_config_path to a target directory path:Anyway::Settings.default_config_path = "/etc/configs"
Anyway::Settings.default_config_path to a Proc, which accepts a config name and returns the path:Anyway::Settings.default_config_path = ->(name) { Rails.root.join("data", "configs", "#{name}.yml") }
_CONF env variable, e.g., MYCOOLGEM_CONF=path/to/cool.ymlENV['MYCOOLGEM_*'].Environmental variables for your config should start with your config name, upper-cased.
For example, if your config name is "mycoolgem", then the env var "MYCOOLGEM_PASSWORD" is used as config.password.
By default, environment variables are automatically type cast (rules are case-insensitive):
"true", "t", "yes" and "y" to true;"false", "f", "no" and "n" to false;"nil" and "null" to nil (do you really need it?);"123" to 123 and "3.14" to 3.14.Type coercion can be customized or disabled.
Anyway Config supports nested (hashed) env variables—just separate keys with double-underscore.
For example, "MYCOOLGEM_OPTIONS__VERBOSE" is parsed as config.options["verbose"].
Array values are also supported:
# Suppose ENV["MYCOOLGEM_IDS"] = '1,2,3'
config.ids #=> [1,2,3]
If you want to provide a text-like env variable which contains commas then wrap it into quotes:
MYCOOLGEM = "Nif-Nif, Naf-Naf and Nouf-Nouf"
You can define custom type coercion rules to convert string data to config values. To do that, use .coerce_types method:
class CoolConfig true
Type coercion is especially useful to deal with array values:
# To define an array type, provide a hash with two keys:
# - type — elements type
# - array: true — mark the parameter as array
coerce_types list: {type: :string, array: true}
You can use type: nil in case you don't want to coerce values, just convert a value into an array:
# From AnyCable config (sentinels could be represented via strings or hashes)
coerce_types redis_sentinels: {type: nil, array: true}
It's also could be useful to explicitly define non-array types (to avoid confusion):
coerce_types non_list: :string
Finally, it's possible to disable auto-casting for a particular config completely:
class CoolConfig true
IMPORTANT: Values provided explicitly (via attribute writers) are not coerced. Coercion is only happening during the load phase.
The following types are supported out-of-the-box: :string, :integer, :integer! (strict integer), :float, :date, :datetime, :uri, :boolean.
You can use custom deserializers by passing a callable object instead of a type name:
COLOR_TO_HEX = lambda do |raw|
case raw
when "red"
"#ff0000"
when "green"
"#00ff00"
when "blue"
"#0000ff"
end
end
class CoolConfig "#ff0000"
It's useful to have a personal, user-specific configuration in development, which extends the project-wide one.
We support this by looking at local files when loading the conf
暂无开放 Issues,或尚未同步最近议题。