anyway_config 1.4.4 → 2.0.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +187 -51
- data/lib/anyway.rb +22 -2
- data/lib/anyway/config.rb +116 -98
- data/lib/anyway/dynamic_config.rb +27 -0
- data/lib/anyway/env.rb +2 -5
- data/lib/anyway/ext/deep_dup.rb +4 -4
- data/lib/anyway/ext/deep_freeze.rb +5 -0
- data/lib/anyway/ext/jruby.rb +9 -4
- data/lib/anyway/ext/string_serialize.rb +1 -7
- data/{spec/dummy/config.ru → lib/anyway/loaders/env_loader.rb} +0 -0
- data/lib/anyway/loaders/secrets_loader.rb +0 -0
- data/lib/anyway/loaders/yaml_loader.rb +0 -0
- data/lib/anyway/option_parser_builder.rb +2 -2
- data/lib/anyway/optparse_config.rb +90 -0
- data/lib/anyway/rails/config.rb +76 -24
- data/lib/anyway/railtie.rb +11 -0
- data/lib/anyway/testing.rb +13 -0
- data/lib/anyway/testing/helpers.rb +36 -0
- data/lib/anyway/version.rb +1 -1
- metadata +46 -48
- data/.gem_release.yml +0 -3
- data/.gitignore +0 -40
- data/.rubocop.yml +0 -50
- data/.travis.yml +0 -30
- data/CHANGELOG.md +0 -112
- data/Gemfile +0 -21
- data/Rakefile +0 -23
- data/anyway_config.gemspec +0 -29
- data/config/cool.yml +0 -5
- data/gemfiles/jruby.gemfile +0 -7
- data/gemfiles/rails42.gemfile +0 -6
- data/gemfiles/rails5.gemfile +0 -6
- data/gemfiles/railsmaster.gemfile +0 -7
- data/spec/anyway.yml +0 -2
- data/spec/config_spec.rb +0 -337
- data/spec/config_spec_norails.rb +0 -86
- data/spec/dummy/config/application.rb +0 -13
- data/spec/dummy/config/boot.rb +0 -5
- data/spec/dummy/config/cool.yml +0 -5
- data/spec/dummy/config/cool_custom.yml +0 -2
- data/spec/dummy/config/database.yml +0 -25
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/test.rb +0 -2
- data/spec/dummy/config/routes.rb +0 -2
- data/spec/dummy/config/secrets.yml +0 -30
- data/spec/env_spec.rb +0 -50
- data/spec/ext/deep_dup_spec.rb +0 -38
- data/spec/ext/deep_freeze_spec.rb +0 -32
- data/spec/ext/hash_spec.rb +0 -39
- data/spec/ext/string_serialize_spec.rb +0 -32
- data/spec/spec_helper.rb +0 -31
- data/spec/spec_norails_helper.rb +0 -26
- data/spec/support/cool_config.rb +0 -10
- data/spec/support/print_warning_matcher.rb +0 -34
- data/spec/support/small_config.rb +0 -7
- data/spec/support/test_config.rb +0 -16
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anyway
|
4
|
+
# Adds ability to generate anonymous (class-less) config dynamicly
|
5
|
+
# (like Rails.application.config_for but using more data sources).
|
6
|
+
module DynamicConfig
|
7
|
+
module ClassMethods
|
8
|
+
# Load config as Hash by any name
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# my_config = Anyway::Config.for(:my_app)
|
13
|
+
# # will load data from config/my_app.yml, secrets.my_app, ENV["MY_APP_*"]
|
14
|
+
#
|
15
|
+
def for(name, **options)
|
16
|
+
config = allocate
|
17
|
+
options[:env_prefix] ||= name.to_s.upcase
|
18
|
+
options[:config_path] ||= config.resolve_config_path(name, options[:env_prefix])
|
19
|
+
config.load_from_sources(name: name, **options)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.included(base)
|
24
|
+
base.extend ClassMethods
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/anyway/env.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'anyway/ext/deep_dup'
|
4
|
-
require 'anyway/ext/string_serialize'
|
5
|
-
|
6
3
|
module Anyway
|
7
4
|
# Parses environment variables and provides
|
8
5
|
# method-like access
|
@@ -19,7 +16,7 @@ module Anyway
|
|
19
16
|
end
|
20
17
|
|
21
18
|
def fetch(prefix)
|
22
|
-
@data[prefix] ||= parse_env(prefix
|
19
|
+
@data[prefix] ||= parse_env(prefix)
|
23
20
|
@data[prefix].deep_dup
|
24
21
|
end
|
25
22
|
|
@@ -29,7 +26,7 @@ module Anyway
|
|
29
26
|
ENV.each_pair.with_object({}) do |(key, val), data|
|
30
27
|
next unless key.start_with?(prefix)
|
31
28
|
|
32
|
-
path = key.sub(/^#{prefix}_/,
|
29
|
+
path = key.sub(/^#{prefix}_/, "").downcase
|
33
30
|
set_by_path(data, path, val.serialize)
|
34
31
|
end
|
35
32
|
end
|
data/lib/anyway/ext/deep_dup.rb
CHANGED
@@ -22,6 +22,11 @@ module Anyway
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
begin
|
26
|
+
require "active_support/core_ext/hash/indifferent_access"
|
27
|
+
rescue LoadError
|
28
|
+
end
|
29
|
+
|
25
30
|
if defined?(::ActiveSupport::HashWithIndifferentAccess)
|
26
31
|
refine ::ActiveSupport::HashWithIndifferentAccess do
|
27
32
|
def deep_freeze
|
data/lib/anyway/ext/jruby.rb
CHANGED
@@ -13,10 +13,10 @@ module Anyway
|
|
13
13
|
def deep_dup
|
14
14
|
each_with_object(dup) do |(key, value), hash|
|
15
15
|
hash[key] = if value.is_a?(::Hash) || value.is_a?(::Array)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
value.deep_dup
|
17
|
+
else
|
18
|
+
value
|
19
|
+
end
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -74,6 +74,11 @@ module Anyway
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
begin
|
78
|
+
require "active_support/core_ext/hash/indifferent_access"
|
79
|
+
rescue LoadError
|
80
|
+
end
|
81
|
+
|
77
82
|
if defined?(::ActiveSupport::HashWithIndifferentAccess)
|
78
83
|
refine ::ActiveSupport::HashWithIndifferentAccess do
|
79
84
|
def deep_freeze
|
@@ -10,14 +10,10 @@ module Anyway
|
|
10
10
|
ARRAY_RXP = /\A[^'"].*\s*,\s*.*[^'"]\z/
|
11
11
|
|
12
12
|
refine ::String do
|
13
|
-
# rubocop:disable Metrics/MethodLength
|
14
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
15
13
|
def serialize
|
16
14
|
case self
|
17
15
|
when ARRAY_RXP
|
18
|
-
# rubocop:disable Style/SymbolProc
|
19
16
|
split(/\s*,\s*/).map { |word| word.serialize }
|
20
|
-
# rubocop:enable Style/SymbolProc
|
21
17
|
when /\A(true|t|yes|y)\z/i
|
22
18
|
true
|
23
19
|
when /\A(false|f|no|n)\z/i
|
@@ -29,13 +25,11 @@ module Anyway
|
|
29
25
|
when /\A\d*\.\d+\z/
|
30
26
|
to_f
|
31
27
|
when /\A['"].*['"]\z/
|
32
|
-
gsub(/(\A['"]|['"]\z)/,
|
28
|
+
gsub(/(\A['"]|['"]\z)/, "")
|
33
29
|
else
|
34
30
|
self
|
35
31
|
end
|
36
32
|
end
|
37
|
-
# rubocop:enable Metrics/MethodLength
|
38
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
39
33
|
end
|
40
34
|
|
41
35
|
using self
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "optparse"
|
4
4
|
|
5
5
|
module Anyway # :nodoc:
|
6
6
|
# Initializes the OptionParser instance using the given configuration
|
@@ -19,7 +19,7 @@ module Anyway # :nodoc:
|
|
19
19
|
private
|
20
20
|
|
21
21
|
def option_parser_on_args(key, flag: false, desc: nil)
|
22
|
-
on_args = ["--#{key.to_s.tr(
|
22
|
+
on_args = ["--#{key.to_s.tr("_", "-")}#{flag ? "" : " VALUE"}"]
|
23
23
|
on_args << desc unless desc.nil?
|
24
24
|
on_args
|
25
25
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "anyway/option_parser_builder"
|
4
|
+
|
5
|
+
require "anyway/ext/deep_dup"
|
6
|
+
require "anyway/ext/string_serialize"
|
7
|
+
|
8
|
+
module Anyway
|
9
|
+
using Anyway::Ext::DeepDup
|
10
|
+
using Anyway::Ext::StringSerialize
|
11
|
+
|
12
|
+
# Adds ability to use script options as the source
|
13
|
+
# of configuration (via optparse)
|
14
|
+
module OptparseConfig
|
15
|
+
module ClassMethods
|
16
|
+
def ignore_options(*args)
|
17
|
+
args.each do |name|
|
18
|
+
option_parser_descriptors[name.to_s][:ignore] = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def describe_options(**hargs)
|
23
|
+
hargs.each do |name, desc|
|
24
|
+
option_parser_descriptors[name.to_s][:desc] = desc
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def flag_options(*args)
|
29
|
+
args.each do |name|
|
30
|
+
option_parser_descriptors[name.to_s][:flag] = true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def extend_options(&block)
|
35
|
+
option_parser_extensions << block
|
36
|
+
end
|
37
|
+
|
38
|
+
def option_parser_options
|
39
|
+
config_attributes.each_with_object({}) do |key, result|
|
40
|
+
descriptor = option_parser_descriptors[key.to_s]
|
41
|
+
next if descriptor[:ignore] == true
|
42
|
+
|
43
|
+
result[key] = descriptor
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def option_parser_extensions
|
48
|
+
return @option_parser_extensions if instance_variable_defined?(:@option_parser_extensions)
|
49
|
+
|
50
|
+
@option_parser_extensions =
|
51
|
+
if superclass < Anyway::Config
|
52
|
+
superclass.option_parser_extensions.dup
|
53
|
+
else
|
54
|
+
[]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def option_parser_descriptors
|
59
|
+
return @option_parser_descriptors if instance_variable_defined?(:@option_parser_descriptors)
|
60
|
+
|
61
|
+
@option_parser_descriptors =
|
62
|
+
if superclass < Anyway::Config
|
63
|
+
superclass.option_parser_descriptors.deep_dup
|
64
|
+
else
|
65
|
+
Hash.new { |h, k| h[k] = {} }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def option_parser
|
71
|
+
@option_parser ||= begin
|
72
|
+
OptionParserBuilder.call(self.class.option_parser_options) do |key, arg|
|
73
|
+
set_value(key, arg.is_a?(String) ? arg.serialize : arg)
|
74
|
+
end.tap do |parser|
|
75
|
+
self.class.option_parser_extensions.map do |extension|
|
76
|
+
extension.call(parser, self)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def parse_options!(options)
|
83
|
+
option_parser.parse!(options)
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.included(base)
|
87
|
+
base.extend ClassMethods
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/anyway/rails/config.rb
CHANGED
@@ -1,38 +1,90 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
4
|
+
|
3
5
|
module Anyway
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
module Rails
|
7
|
+
# Enhance config to be more Railsy-like:
|
8
|
+
# – accept hashes with indeferent access
|
9
|
+
# - load data from secrets
|
10
|
+
# - recognize Rails env when loading from YML
|
11
|
+
module Config
|
12
|
+
module ClassMethods
|
13
|
+
# Make defaults to be a Hash with indifferent access
|
14
|
+
def defaults
|
15
|
+
return @defaults if instance_variable_defined?(:@defaults)
|
8
16
|
|
9
|
-
|
17
|
+
@defaults = super.with_indifferent_access
|
18
|
+
end
|
10
19
|
end
|
11
|
-
end
|
12
20
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
def load_from_sources(**options)
|
22
|
+
base_config = {}.with_indifferent_access
|
23
|
+
each_source(options) do |config|
|
24
|
+
base_config.deep_merge!(config) if config
|
25
|
+
end
|
26
|
+
base_config
|
27
|
+
end
|
19
28
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
29
|
+
def each_source(options)
|
30
|
+
yield load_from_file(options)
|
31
|
+
yield load_from_secrets(options)
|
32
|
+
yield load_from_credentials(options)
|
33
|
+
yield load_from_env(options)
|
34
|
+
end
|
24
35
|
|
25
|
-
|
26
|
-
|
27
|
-
|
36
|
+
def load_from_file(name:, config_path:, env_prefix:, **_options)
|
37
|
+
file_config = load_from_yml(config_path)[::Rails.env] || {}
|
38
|
+
|
39
|
+
if Anyway::Settings.use_local_files
|
40
|
+
local_config_path = config_path.sub(/\.yml/, ".local.yml")
|
41
|
+
file_config.deep_merge!(load_from_yml(local_config_path) || {})
|
42
|
+
end
|
43
|
+
|
44
|
+
file_config
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_from_secrets(name:, **_options)
|
48
|
+
return unless ::Rails.application.respond_to?(:secrets)
|
49
|
+
|
50
|
+
::Rails.application.secrets.public_send(name)
|
28
51
|
end
|
29
|
-
config
|
30
|
-
end
|
31
52
|
|
32
|
-
|
53
|
+
def load_from_credentials(name:, **_options)
|
54
|
+
# do not load from credentials if we're in the context
|
55
|
+
# of the `credentials:edit` command
|
56
|
+
return if defined?(::Rails::Command::CredentialsCommand)
|
33
57
|
|
34
|
-
|
35
|
-
|
58
|
+
return unless ::Rails.application.respond_to?(:credentials)
|
59
|
+
|
60
|
+
# Create a new hash cause credentials are mutable!
|
61
|
+
creds_config = {}
|
62
|
+
|
63
|
+
creds_config.deep_merge!(::Rails.application.credentials.public_send(name) || {})
|
64
|
+
|
65
|
+
creds_config.deep_merge!(load_from_local_credentials(name: name)) if Anyway::Settings.use_local_files
|
66
|
+
creds_config
|
67
|
+
end
|
68
|
+
|
69
|
+
def load_from_local_credentials(name:)
|
70
|
+
local_creds_path = ::Rails.root.join("config/credentials/local.yml.enc").to_s
|
71
|
+
|
72
|
+
return unless File.file?(local_creds_path)
|
73
|
+
|
74
|
+
creds = ::Rails.application.encrypted(
|
75
|
+
local_creds_path,
|
76
|
+
key_path: ::Rails.root.join("config/credentials/local.key")
|
77
|
+
)
|
78
|
+
|
79
|
+
creds.public_send(name) || {}
|
80
|
+
end
|
81
|
+
|
82
|
+
def default_config_path(name)
|
83
|
+
::Rails.root.join("config", "#{name}.yml")
|
84
|
+
end
|
36
85
|
end
|
37
86
|
end
|
38
87
|
end
|
88
|
+
|
89
|
+
Anyway::Config.prepend Anyway::Rails::Config
|
90
|
+
Anyway::Config.singleton_class.prepend Anyway::Rails::Config::ClassMethods
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anyway # :nodoc:
|
4
|
+
class Railtie < ::Rails::Railtie # :nodoc:
|
5
|
+
# Add settings to Rails config
|
6
|
+
config.anyway_config = Anyway::Settings
|
7
|
+
|
8
|
+
# Allow autoloading of app/configs in configuration files
|
9
|
+
ActiveSupport::Dependencies.autoload_paths << "app/configs"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Anyway
|
4
|
+
module Testing
|
5
|
+
module Helpers
|
6
|
+
# Sets the ENV variables to the provided
|
7
|
+
# values and restore outside the block
|
8
|
+
#
|
9
|
+
# Also resets Anyway.env before and after calling the block
|
10
|
+
# to make sure that the values are not cached.
|
11
|
+
#
|
12
|
+
# NOTE: to remove the env value, pass `nil` as the value
|
13
|
+
def with_env(data)
|
14
|
+
was_values = []
|
15
|
+
|
16
|
+
data.each do |key, val|
|
17
|
+
was_values << [key, ENV[key]]
|
18
|
+
next ENV.delete(key) if val.nil?
|
19
|
+
ENV[key] = val
|
20
|
+
end
|
21
|
+
|
22
|
+
# clear cached env values
|
23
|
+
Anyway.env.clear
|
24
|
+
yield
|
25
|
+
ensure
|
26
|
+
was_values.each do |(key, val)|
|
27
|
+
next ENV.delete(key) if val.nil?
|
28
|
+
ENV[key] = val
|
29
|
+
end
|
30
|
+
|
31
|
+
# clear cache again
|
32
|
+
Anyway.env.clear
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/anyway/version.rb
CHANGED