anyway_config 2.0.6 → 2.1.0
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/CHANGELOG.md +199 -181
- data/README.md +69 -9
- data/lib/.rbnext/1995.next/anyway/config.rb +391 -0
- data/lib/.rbnext/1995.next/anyway/dynamic_config.rb +27 -0
- data/lib/.rbnext/1995.next/anyway/env.rb +56 -0
- data/lib/.rbnext/1995.next/anyway/loaders/base.rb +21 -0
- data/lib/.rbnext/1995.next/anyway/tracing.rb +181 -0
- data/lib/.rbnext/2.7/anyway/config.rb +12 -14
- data/lib/.rbnext/2.7/anyway/rails/loaders/yaml.rb +30 -0
- data/lib/.rbnext/2.7/anyway/settings.rb +79 -0
- data/lib/.rbnext/2.7/anyway/tracing.rb +8 -6
- data/lib/.rbnext/{2.8 → 3.0}/anyway/config.rb +12 -14
- data/lib/.rbnext/{2.8 → 3.0}/anyway/loaders.rb +0 -0
- data/lib/.rbnext/{2.8 → 3.0}/anyway/loaders/base.rb +0 -0
- data/lib/.rbnext/{2.8 → 3.0}/anyway/tracing.rb +8 -6
- data/lib/anyway/config.rb +26 -28
- data/lib/anyway/dynamic_config.rb +1 -1
- data/lib/anyway/env.rb +1 -1
- data/lib/anyway/ext/deep_dup.rb +6 -0
- data/lib/anyway/ext/hash.rb +0 -12
- data/lib/anyway/loaders/base.rb +1 -1
- data/lib/anyway/loaders/yaml.rb +3 -3
- data/lib/anyway/rails/loaders/credentials.rb +2 -2
- data/lib/anyway/rails/loaders/secrets.rb +1 -1
- data/lib/anyway/rails/loaders/yaml.rb +11 -0
- data/lib/anyway/rails/settings.rb +6 -0
- data/lib/anyway/settings.rb +52 -2
- data/lib/anyway/tracing.rb +4 -4
- data/lib/anyway/utils/deep_merge.rb +21 -0
- data/lib/anyway/version.rb +1 -1
- data/lib/anyway_config.rb +2 -0
- metadata +18 -10
| @@ -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(new_empty_config, name: name, **options)
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def self.included(base)
         | 
| 24 | 
            +
                  base.extend ClassMethods
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Anyway
         | 
| 4 | 
            +
              # Parses environment variables and provides
         | 
| 5 | 
            +
              # method-like access
         | 
| 6 | 
            +
              class Env
         | 
| 7 | 
            +
                using RubyNext
         | 
| 8 | 
            +
                using Anyway::Ext::DeepDup
         | 
| 9 | 
            +
                using Anyway::Ext::Hash
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                include Tracing
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                attr_reader :data, :traces, :type_cast
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def initialize(type_cast: AutoCast)
         | 
| 16 | 
            +
                  @type_cast = type_cast
         | 
| 17 | 
            +
                  @data = {}
         | 
| 18 | 
            +
                  @traces = {}
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def clear
         | 
| 22 | 
            +
                  data.clear
         | 
| 23 | 
            +
                  traces.clear
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def fetch(prefix)
         | 
| 27 | 
            +
                  return data[prefix].deep_dup if data.key?(prefix)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  Tracing.capture do
         | 
| 30 | 
            +
                    data[prefix] = parse_env(prefix)
         | 
| 31 | 
            +
                  end.then do |trace|
         | 
| 32 | 
            +
                    traces[prefix] = trace
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  data[prefix].deep_dup
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def fetch_with_trace(prefix)
         | 
| 39 | 
            +
                  [fetch(prefix), traces[prefix]]
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                private
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def parse_env(prefix)
         | 
| 45 | 
            +
                  match_prefix = "#{prefix}_"
         | 
| 46 | 
            +
                  ENV.each_pair.with_object({}) do |(key, val), data|
         | 
| 47 | 
            +
                    next unless key.start_with?(match_prefix)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    path = key.sub(/^#{prefix}_/, "").downcase
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    paths = path.split("__")
         | 
| 52 | 
            +
                    trace!(:env, *paths, key: key) { data.bury(type_cast.call(val), *paths) }
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Anyway
         | 
| 4 | 
            +
              module Loaders
         | 
| 5 | 
            +
                class Base
         | 
| 6 | 
            +
                  include Tracing
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  class << self
         | 
| 9 | 
            +
                    def call(local: Anyway::Settings.use_local_files, **opts)
         | 
| 10 | 
            +
                      new(local: local).call(**opts)
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def initialize(local:)
         | 
| 15 | 
            +
                    @local = local
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def use_local?() = @local == true
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,181 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Anyway
         | 
| 4 | 
            +
              # Provides method to trace values association
         | 
| 5 | 
            +
              module Tracing
         | 
| 6 | 
            +
                using Anyway::Ext::DeepDup
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                using(Module.new do
         | 
| 9 | 
            +
                  refine Hash do
         | 
| 10 | 
            +
                    def inspect
         | 
| 11 | 
            +
                      "{#{map { |k, v| "#{k}: #{v.inspect}" }.join(", ")}}"
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  refine Thread::Backtrace::Location do
         | 
| 16 | 
            +
                    def path_lineno() = "#{path}:#{lineno}"
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                class Trace
         | 
| 21 | 
            +
                  UNDEF = Object.new
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  attr_reader :type, :value, :source
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def initialize(type = :trace, value = UNDEF, **source)
         | 
| 26 | 
            +
                    @type = type
         | 
| 27 | 
            +
                    @source = source
         | 
| 28 | 
            +
                    @value = value == UNDEF ? Hash.new { |h, k| h[k] = Trace.new(:trace) } : value
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def dig(...)
         | 
| 32 | 
            +
                    value.dig(...)
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def record_value(val, *path, **opts)
         | 
| 36 | 
            +
                    key = path.pop
         | 
| 37 | 
            +
                    if val.is_a?(Hash)
         | 
| 38 | 
            +
                      Trace.new.tap { _1.merge_values(val, **opts) }
         | 
| 39 | 
            +
                    else
         | 
| 40 | 
            +
                      Trace.new(:value, val, **opts)
         | 
| 41 | 
            +
                    end => trace
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    target_trace = path.empty? ? self : value.dig(*path)
         | 
| 44 | 
            +
                    target_trace.value[key.to_s] = trace
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    val
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def merge_values(hash, **opts)
         | 
| 50 | 
            +
                    return hash unless hash
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    hash.each do |key, val|
         | 
| 53 | 
            +
                      if val.is_a?(Hash)
         | 
| 54 | 
            +
                        value[key.to_s].merge_values(val, **opts)
         | 
| 55 | 
            +
                      else
         | 
| 56 | 
            +
                        value[key.to_s] = Trace.new(:value, val, **opts)
         | 
| 57 | 
            +
                      end
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    hash
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  def merge!(another_trace)
         | 
| 64 | 
            +
                    raise ArgumentError, "You can only merge into a :trace type, and this is :#{type}" unless trace?
         | 
| 65 | 
            +
                    raise ArgumentError, "You can only merge a :trace type, but trying :#{type}" unless another_trace.trace?
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    another_trace.value.each do |key, sub_trace|
         | 
| 68 | 
            +
                      if sub_trace.trace?
         | 
| 69 | 
            +
                        value[key].merge! sub_trace
         | 
| 70 | 
            +
                      else
         | 
| 71 | 
            +
                        value[key] = sub_trace
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  def keep_if(...)
         | 
| 77 | 
            +
                    raise ArgumentError, "You can only filter :trace type, and this is :#{type}" unless trace?
         | 
| 78 | 
            +
                    value.keep_if(...)
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  def clear() = value.clear
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  def trace?() = type == :trace
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def to_h
         | 
| 86 | 
            +
                    if trace?
         | 
| 87 | 
            +
                      value.transform_values(&:to_h).tap { _1.default_proc = nil }
         | 
| 88 | 
            +
                    else
         | 
| 89 | 
            +
                      {value: value, source: source}
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  def dup() = self.class.new(type, value.dup, **source)
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  def pretty_print(q)
         | 
| 96 | 
            +
                    if trace?
         | 
| 97 | 
            +
                      q.nest(2) do
         | 
| 98 | 
            +
                        q.breakable ""
         | 
| 99 | 
            +
                        q.seplist(value, nil, :each) do |k, v|
         | 
| 100 | 
            +
                          q.group do
         | 
| 101 | 
            +
                            q.text k
         | 
| 102 | 
            +
                            q.text " =>"
         | 
| 103 | 
            +
                            q.breakable " " unless v.trace?
         | 
| 104 | 
            +
                            q.pp v
         | 
| 105 | 
            +
                          end
         | 
| 106 | 
            +
                        end
         | 
| 107 | 
            +
                      end
         | 
| 108 | 
            +
                    else
         | 
| 109 | 
            +
                      q.pp value
         | 
| 110 | 
            +
                      q.group(0, " (", ")") do
         | 
| 111 | 
            +
                        q.seplist(source, lambda { q.breakable " " }, :each) do |k, v|
         | 
| 112 | 
            +
                          q.group do
         | 
| 113 | 
            +
                            q.text k.to_s
         | 
| 114 | 
            +
                            q.text "="
         | 
| 115 | 
            +
                            q.text v.to_s
         | 
| 116 | 
            +
                          end
         | 
| 117 | 
            +
                        end
         | 
| 118 | 
            +
                      end
         | 
| 119 | 
            +
                    end
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                class << self
         | 
| 124 | 
            +
                  def capture
         | 
| 125 | 
            +
                    unless Settings.tracing_enabled
         | 
| 126 | 
            +
                      yield
         | 
| 127 | 
            +
                      return
         | 
| 128 | 
            +
                    end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                    trace = Trace.new
         | 
| 131 | 
            +
                    trace_stack.push trace
         | 
| 132 | 
            +
                    yield
         | 
| 133 | 
            +
                    trace_stack.last
         | 
| 134 | 
            +
                  ensure
         | 
| 135 | 
            +
                    trace_stack.pop
         | 
| 136 | 
            +
                  end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                  def trace_stack
         | 
| 139 | 
            +
                    (Thread.current[:__anyway__trace_stack__] ||= [])
         | 
| 140 | 
            +
                  end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  def current_trace() = trace_stack.last
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                  alias_method :tracing?, :current_trace
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  def source_stack
         | 
| 147 | 
            +
                    (Thread.current[:__anyway__trace_source_stack__] ||= [])
         | 
| 148 | 
            +
                  end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  def current_trace_source
         | 
| 151 | 
            +
                    source_stack.last || accessor_source(caller_locations(2, 1).first)
         | 
| 152 | 
            +
                  end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                  def with_trace_source(src)
         | 
| 155 | 
            +
                    source_stack << src
         | 
| 156 | 
            +
                    yield
         | 
| 157 | 
            +
                  ensure
         | 
| 158 | 
            +
                    source_stack.pop
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                  private
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                  def accessor_source(location)
         | 
| 164 | 
            +
                    {type: :accessor, called_from: location.path_lineno}
         | 
| 165 | 
            +
                  end
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                module_function
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                def trace!(type, *path, **opts)
         | 
| 171 | 
            +
                  return yield unless Tracing.tracing?
         | 
| 172 | 
            +
                  val = yield
         | 
| 173 | 
            +
                  if val.is_a?(Hash)
         | 
| 174 | 
            +
                    Tracing.current_trace.merge_values(val, type: type, **opts)
         | 
| 175 | 
            +
                  else
         | 
| 176 | 
            +
                    Tracing.current_trace.record_value(val, *path, type: type, **opts)
         | 
| 177 | 
            +
                  end
         | 
| 178 | 
            +
                  val
         | 
| 179 | 
            +
                end
         | 
| 180 | 
            +
              end
         | 
| 181 | 
            +
            end
         | 
| @@ -19,7 +19,7 @@ module Anyway # :nodoc: | |
| 19 19 | 
             
              # Provides `attr_config` method to describe
         | 
| 20 20 | 
             
              # configuration parameters and set defaults
         | 
| 21 21 | 
             
              class Config
         | 
| 22 | 
            -
                PARAM_NAME = /^[a-z_]( | 
| 22 | 
            +
                PARAM_NAME = /^[a-z_](\w+)?$/
         | 
| 23 23 |  | 
| 24 24 | 
             
                # List of names that couldn't be used as config names
         | 
| 25 25 | 
             
                # (the class instance methods we use)
         | 
| @@ -40,12 +40,14 @@ module Anyway # :nodoc: | |
| 40 40 | 
             
                  raise_validation_error
         | 
| 41 41 | 
             
                  reload
         | 
| 42 42 | 
             
                  resolve_config_path
         | 
| 43 | 
            +
                  tap
         | 
| 43 44 | 
             
                  to_h
         | 
| 44 45 | 
             
                  to_source_trace
         | 
| 45 46 | 
             
                  write_config_attr
         | 
| 46 47 | 
             
                ].freeze
         | 
| 47 48 |  | 
| 48 49 | 
             
                class Error < StandardError; end
         | 
| 50 | 
            +
             | 
| 49 51 | 
             
                class ValidationError < Error; end
         | 
| 50 52 |  | 
| 51 53 | 
             
                include OptparseConfig
         | 
| @@ -142,9 +144,9 @@ module Anyway # :nodoc: | |
| 142 144 | 
             
                  end
         | 
| 143 145 |  | 
| 144 146 | 
             
                  def on_load(*names, &block)
         | 
| 145 | 
            -
                    raise ArgumentError, "Either methods or block should be specified, not both" if  | 
| 147 | 
            +
                    raise ArgumentError, "Either methods or block should be specified, not both" if block && !names.empty?
         | 
| 146 148 |  | 
| 147 | 
            -
                    if  | 
| 149 | 
            +
                    if block
         | 
| 148 150 | 
             
                      load_callbacks << BlockCallback.new(block)
         | 
| 149 151 | 
             
                    else
         | 
| 150 152 | 
             
                      load_callbacks.push(*names.map { |_1| NamedCallback.new(_1) })
         | 
| @@ -201,8 +203,7 @@ module Anyway # :nodoc: | |
| 201 203 | 
             
                      accessors_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
         | 
| 202 204 | 
             
                        def #{name}=(val)
         | 
| 203 205 | 
             
                          __trace__&.record_value(val, \"#{name}\", **Tracing.current_trace_source)
         | 
| 204 | 
            -
                           | 
| 205 | 
            -
                          @#{name} = values[:#{name}] = val
         | 
| 206 | 
            +
                          values[:#{name}] = val
         | 
| 206 207 | 
             
                        end
         | 
| 207 208 |  | 
| 208 209 | 
             
                        def #{name}
         | 
| @@ -229,7 +230,7 @@ module Anyway # :nodoc: | |
| 229 230 | 
             
                    # handle two cases:
         | 
| 230 231 | 
             
                    # - SomeModule::Config => "some_module"
         | 
| 231 232 | 
             
                    # - SomeConfig => "some"
         | 
| 232 | 
            -
                    unless name =~ /^(\w+)( | 
| 233 | 
            +
                    unless name =~ /^(\w+)(::)?Config$/
         | 
| 233 234 | 
             
                      raise "Couldn't infer config name, please, specify it explicitly" \
         | 
| 234 235 | 
             
                        "via `config_name :my_config`"
         | 
| 235 236 | 
             
                    end
         | 
| @@ -288,17 +289,14 @@ module Anyway # :nodoc: | |
| 288 289 | 
             
                  trace = Tracing.capture do
         | 
| 289 290 | 
             
                    Tracing.trace!(:defaults) { base_config }
         | 
| 290 291 |  | 
| 291 | 
            -
                     | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 294 | 
            -
                      env_prefix: env_prefix,
         | 
| 295 | 
            -
                      config_path: resolve_config_path(config_name, env_prefix)
         | 
| 296 | 
            -
                    )
         | 
| 292 | 
            +
                    config_path = resolve_config_path(config_name, env_prefix)
         | 
| 293 | 
            +
             | 
| 294 | 
            +
                    load_from_sources(base_config, name: config_name, env_prefix: env_prefix, config_path: config_path)
         | 
| 297 295 |  | 
| 298 296 | 
             
                    if overrides
         | 
| 299 297 | 
             
                      Tracing.trace!(:load) { overrides }
         | 
| 300 298 |  | 
| 301 | 
            -
                       | 
| 299 | 
            +
                      Utils.deep_merge!(base_config, overrides)
         | 
| 302 300 | 
             
                    end
         | 
| 303 301 | 
             
                  end
         | 
| 304 302 |  | 
| @@ -321,7 +319,7 @@ module Anyway # :nodoc: | |
| 321 319 |  | 
| 322 320 | 
             
                def load_from_sources(base_config, **options)
         | 
| 323 321 | 
             
                  Anyway.loaders.each do |(_id, loader)|
         | 
| 324 | 
            -
                     | 
| 322 | 
            +
                    Utils.deep_merge!(base_config, loader.call(**options))
         | 
| 325 323 | 
             
                  end
         | 
| 326 324 | 
             
                  base_config
         | 
| 327 325 | 
             
                end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Anyway
         | 
| 4 | 
            +
              module Rails
         | 
| 5 | 
            +
                module Loaders
         | 
| 6 | 
            +
                  class YAML < Anyway::Loaders::YAML
         | 
| 7 | 
            +
                    def load_base_yml(*)
         | 
| 8 | 
            +
                      parsed_yml = super
         | 
| 9 | 
            +
                      return parsed_yml unless environmental?(parsed_yml)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                      super[::Rails.env] || {}
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    private
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    def environmental?(parsed_yml)
         | 
| 17 | 
            +
                      return true unless Settings.future.unwrap_known_environments
         | 
| 18 | 
            +
                      # likely
         | 
| 19 | 
            +
                      return true if parsed_yml.key?(::Rails.env)
         | 
| 20 | 
            +
                      # less likely
         | 
| 21 | 
            +
                      ::Rails.application.config.anyway_config.known_environments.any? { |_1| parsed_yml.key?(_1) }
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    def relative_config_path(path)
         | 
| 25 | 
            +
                      Pathname.new(path).relative_path_from(::Rails.root)
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,79 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Anyway
         | 
| 4 | 
            +
              # Use Settings name to not confuse with Config.
         | 
| 5 | 
            +
              #
         | 
| 6 | 
            +
              # Settings contain the library-wide configuration.
         | 
| 7 | 
            +
              class Settings
         | 
| 8 | 
            +
                # Future encapsulates settings that will be introduced in the upcoming version
         | 
| 9 | 
            +
                # with the default values, which could break compatibility
         | 
| 10 | 
            +
                class Future
         | 
| 11 | 
            +
                  class << self
         | 
| 12 | 
            +
                    def setting(name, default_value)
         | 
| 13 | 
            +
                      settings[name] = default_value
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      define_method(name) do
         | 
| 16 | 
            +
                        store[name]
         | 
| 17 | 
            +
                      end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      define_method(:"#{name}=") do |val|
         | 
| 20 | 
            +
                        store[name] = val
         | 
| 21 | 
            +
                      end
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    def settings
         | 
| 25 | 
            +
                      @settings ||= {}
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def initialize
         | 
| 30 | 
            +
                    @store = {}
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def use(*names)
         | 
| 34 | 
            +
                    store.clear
         | 
| 35 | 
            +
                    names.each { |_1| store[_1] = self.class.settings[_1] }
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  private
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  attr_reader :store
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                class << self
         | 
| 44 | 
            +
                  # Define whether to load data from
         | 
| 45 | 
            +
                  # *.yml.local (or credentials/local.yml.enc)
         | 
| 46 | 
            +
                  attr_accessor :use_local_files
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  # A proc returning a path to YML config file given the config name
         | 
| 49 | 
            +
                  attr_reader :default_config_path
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  def default_config_path=(val)
         | 
| 52 | 
            +
                    if val.is_a?(Proc)
         | 
| 53 | 
            +
                      @default_config_path = val
         | 
| 54 | 
            +
                      return
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    val = val.to_s
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    @default_config_path = ->(name) { File.join(val, "#{name}.yml") }
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  # Enable source tracing
         | 
| 63 | 
            +
                  attr_accessor :tracing_enabled
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  def future
         | 
| 66 | 
            +
                    @future ||= Future.new
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                # By default, use local files only in development (that's the purpose if the local files)
         | 
| 71 | 
            +
                self.use_local_files = (ENV["RACK_ENV"] == "development" || ENV["RAILS_ENV"] == "development")
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                # By default, consider configs are stored in the ./config folder
         | 
| 74 | 
            +
                self.default_config_path = ->(name) { "./config/#{name}.yml" }
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                # Tracing is enabled by default
         | 
| 77 | 
            +
                self.tracing_enabled = true
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
            end
         |