qonfig 0.0.0 → 0.12.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/.gitignore +6 -2
- data/.jrubyrc +1 -0
- data/.rspec +1 -1
- data/.rubocop.yml +15 -0
- data/.travis.yml +43 -4
- data/CHANGELOG.md +121 -0
- data/Gemfile +4 -2
- data/LICENSE.txt +1 -1
- data/README.md +1060 -19
- data/Rakefile +18 -4
- data/bin/console +5 -11
- data/bin/rspec +55 -0
- data/bin/setup +1 -0
- data/gemfiles/with_external_deps.gemfile +8 -0
- data/gemfiles/without_external_deps.gemfile +5 -0
- data/lib/qonfig.rb +22 -2
- data/lib/qonfig/command_set.rb +67 -0
- data/lib/qonfig/commands.rb +15 -0
- data/lib/qonfig/commands/add_nested_option.rb +45 -0
- data/lib/qonfig/commands/add_option.rb +41 -0
- data/lib/qonfig/commands/base.rb +12 -0
- data/lib/qonfig/commands/compose.rb +37 -0
- data/lib/qonfig/commands/expose_yaml.rb +159 -0
- data/lib/qonfig/commands/load_from_env.rb +95 -0
- data/lib/qonfig/commands/load_from_env/value_converter.rb +84 -0
- data/lib/qonfig/commands/load_from_json.rb +56 -0
- data/lib/qonfig/commands/load_from_self.rb +73 -0
- data/lib/qonfig/commands/load_from_yaml.rb +58 -0
- data/lib/qonfig/configurable.rb +116 -0
- data/lib/qonfig/data_set.rb +213 -0
- data/lib/qonfig/data_set/class_builder.rb +27 -0
- data/lib/qonfig/data_set/validator.rb +7 -0
- data/lib/qonfig/dsl.rb +122 -0
- data/lib/qonfig/errors.rb +111 -0
- data/lib/qonfig/loaders.rb +9 -0
- data/lib/qonfig/loaders/basic.rb +38 -0
- data/lib/qonfig/loaders/json.rb +24 -0
- data/lib/qonfig/loaders/yaml.rb +24 -0
- data/lib/qonfig/plugins.rb +65 -0
- data/lib/qonfig/plugins/abstract.rb +13 -0
- data/lib/qonfig/plugins/access_mixin.rb +38 -0
- data/lib/qonfig/plugins/registry.rb +125 -0
- data/lib/qonfig/plugins/toml.rb +26 -0
- data/lib/qonfig/plugins/toml/commands/expose_toml.rb +146 -0
- data/lib/qonfig/plugins/toml/commands/load_from_toml.rb +49 -0
- data/lib/qonfig/plugins/toml/data_set.rb +19 -0
- data/lib/qonfig/plugins/toml/dsl.rb +27 -0
- data/lib/qonfig/plugins/toml/loaders/toml.rb +24 -0
- data/lib/qonfig/plugins/toml/tomlrb_fixes.rb +92 -0
- data/lib/qonfig/plugins/toml/uploaders/toml.rb +25 -0
- data/lib/qonfig/settings.rb +457 -0
- data/lib/qonfig/settings/builder.rb +18 -0
- data/lib/qonfig/settings/key_guard.rb +71 -0
- data/lib/qonfig/settings/lock.rb +60 -0
- data/lib/qonfig/uploaders.rb +10 -0
- data/lib/qonfig/uploaders/base.rb +18 -0
- data/lib/qonfig/uploaders/file.rb +55 -0
- data/lib/qonfig/uploaders/json.rb +35 -0
- data/lib/qonfig/uploaders/yaml.rb +93 -0
- data/lib/qonfig/version.rb +7 -1
- data/qonfig.gemspec +29 -17
- metadata +122 -16
| @@ -0,0 +1,95 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # @api private
         | 
| 4 | 
            +
            # @since 0.2.0
         | 
| 5 | 
            +
            class Qonfig::Commands::LoadFromENV < Qonfig::Commands::Base
         | 
| 6 | 
            +
              require_relative 'load_from_env/value_converter'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              # @return [Boolean]
         | 
| 9 | 
            +
              #
         | 
| 10 | 
            +
              # @api private
         | 
| 11 | 
            +
              # @since 0.2.0
         | 
| 12 | 
            +
              attr_reader :convert_values
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              # @return [Regexp]
         | 
| 15 | 
            +
              #
         | 
| 16 | 
            +
              # @api private
         | 
| 17 | 
            +
              # @since 0.2.0
         | 
| 18 | 
            +
              attr_reader :prefix_pattern
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              # @return [Boolean]
         | 
| 21 | 
            +
              #
         | 
| 22 | 
            +
              # @api private
         | 
| 23 | 
            +
              # @since 0.2.0
         | 
| 24 | 
            +
              attr_reader :trim_prefix
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              # @return [Regexp]
         | 
| 27 | 
            +
              #
         | 
| 28 | 
            +
              # @api private
         | 
| 29 | 
            +
              # @since 0.2.0
         | 
| 30 | 
            +
              attr_reader :trim_pattern
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              # @option convert_values [Boolean]
         | 
| 33 | 
            +
              # @opion prefix [NilClass, String, Regexp]
         | 
| 34 | 
            +
              #
         | 
| 35 | 
            +
              # @raise [Qonfig::ArgumentError]
         | 
| 36 | 
            +
              #
         | 
| 37 | 
            +
              # @api private
         | 
| 38 | 
            +
              # @since 0.2.0
         | 
| 39 | 
            +
              def initialize(convert_values: false, prefix: nil, trim_prefix: false)
         | 
| 40 | 
            +
                unless convert_values.is_a?(FalseClass) || convert_values.is_a?(TrueClass)
         | 
| 41 | 
            +
                  raise Qonfig::ArgumentError, ':convert_values option should be a boolean'
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                unless prefix.is_a?(NilClass) || prefix.is_a?(String) || prefix.is_a?(Regexp)
         | 
| 45 | 
            +
                  raise Qonfig::ArgumentError, ':prefix option should be a nil / string / regexp'
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                unless trim_prefix.is_a?(FalseClass) || trim_prefix.is_a?(TrueClass)
         | 
| 49 | 
            +
                  raise Qonfig::ArgumentError, ':trim_refix options should be a boolean'
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                @convert_values = convert_values
         | 
| 53 | 
            +
                @prefix_pattern = prefix.is_a?(Regexp) ? prefix : /\A#{Regexp.escape(prefix.to_s)}.*\z/m
         | 
| 54 | 
            +
                @trim_prefix    = trim_prefix
         | 
| 55 | 
            +
                @trim_pattern   = prefix.is_a?(Regexp) ? prefix : /\A(#{Regexp.escape(prefix.to_s)})/m
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              # @param settings [Qonfig::Settings]
         | 
| 59 | 
            +
              # @return [void]
         | 
| 60 | 
            +
              #
         | 
| 61 | 
            +
              # @api private
         | 
| 62 | 
            +
              # @since 0.2.0
         | 
| 63 | 
            +
              def call(settings)
         | 
| 64 | 
            +
                env_data = extract_env_data
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                env_based_settings = build_data_set_class(env_data).new.settings
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                settings.__append_settings__(env_based_settings)
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              private
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              # @return [Hash]
         | 
| 74 | 
            +
              #
         | 
| 75 | 
            +
              # @api private
         | 
| 76 | 
            +
              # @since 0.2.0
         | 
| 77 | 
            +
              def extract_env_data
         | 
| 78 | 
            +
                ENV.each_with_object({}) do |(key, value), env_data|
         | 
| 79 | 
            +
                  next unless key.match(prefix_pattern)
         | 
| 80 | 
            +
                  key = key.sub(trim_pattern, '') if trim_prefix
         | 
| 81 | 
            +
                  env_data[key] = value
         | 
| 82 | 
            +
                end.tap do |env_data|
         | 
| 83 | 
            +
                  ValueConverter.convert_values!(env_data) if convert_values
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
              # @param env_data [Hash]
         | 
| 88 | 
            +
              # @return [Class<Qonfig::DataSet>]
         | 
| 89 | 
            +
              #
         | 
| 90 | 
            +
              # @api private
         | 
| 91 | 
            +
              # @since 0.2.0
         | 
| 92 | 
            +
              def build_data_set_class(env_data)
         | 
| 93 | 
            +
                Qonfig::DataSet::ClassBuilder.build_from_hash(env_data)
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
            end
         | 
| @@ -0,0 +1,84 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Qonfig
         | 
| 4 | 
            +
              # @api private
         | 
| 5 | 
            +
              # @since 0.2.0
         | 
| 6 | 
            +
              module Commands::LoadFromENV::ValueConverter
         | 
| 7 | 
            +
                # @return [Regexp]
         | 
| 8 | 
            +
                #
         | 
| 9 | 
            +
                # @api private
         | 
| 10 | 
            +
                # @since 0.2.0
         | 
| 11 | 
            +
                INTEGER_PATTERN = /\A\d+\z/.freeze
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                # @return [Regexp]
         | 
| 14 | 
            +
                #
         | 
| 15 | 
            +
                # @api private
         | 
| 16 | 
            +
                # @since 0.2.0
         | 
| 17 | 
            +
                FLOAT_PATTERN = /\A\d+\.\d+\z/.freeze
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                # @return [Regexp]
         | 
| 20 | 
            +
                #
         | 
| 21 | 
            +
                # @api private
         | 
| 22 | 
            +
                # @since 0.2.0
         | 
| 23 | 
            +
                TRUE_PATTERN = /\A(t|true)\z/i.freeze
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                # @return [Regexp]
         | 
| 26 | 
            +
                #
         | 
| 27 | 
            +
                # @api private
         | 
| 28 | 
            +
                # @since 0.2.0
         | 
| 29 | 
            +
                FALSE_PATTERN = /\A(f|false)\z/i.freeze
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                # @return [Regexp]
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                # @api private
         | 
| 34 | 
            +
                # @since 0.2.0
         | 
| 35 | 
            +
                ARRAY_PATTERN = /\A[^'"].*\s*,\s*.*[^'"]\z/.freeze
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                # @return [Regexp]
         | 
| 38 | 
            +
                #
         | 
| 39 | 
            +
                # @api private
         | 
| 40 | 
            +
                # @since 0.2.0
         | 
| 41 | 
            +
                QUOTED_STRING_PATTERN = /\A['"].*['"]\z/.freeze
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                class << self
         | 
| 44 | 
            +
                  # @param env_data [Hash]
         | 
| 45 | 
            +
                  # @return [void]
         | 
| 46 | 
            +
                  #
         | 
| 47 | 
            +
                  # @api private
         | 
| 48 | 
            +
                  # @since 0.2.0
         | 
| 49 | 
            +
                  def convert_values!(env_data)
         | 
| 50 | 
            +
                    env_data.each_pair do |key, value|
         | 
| 51 | 
            +
                      env_data[key] = convert_value(value)
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  private
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  # @param value [Object]
         | 
| 58 | 
            +
                  # @return [Object]
         | 
| 59 | 
            +
                  #
         | 
| 60 | 
            +
                  # @api private
         | 
| 61 | 
            +
                  # @since 0.2.0
         | 
| 62 | 
            +
                  def convert_value(value)
         | 
| 63 | 
            +
                    return value unless value.is_a?(String)
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    case value
         | 
| 66 | 
            +
                    when INTEGER_PATTERN
         | 
| 67 | 
            +
                      Integer(value)
         | 
| 68 | 
            +
                    when FLOAT_PATTERN
         | 
| 69 | 
            +
                      Float(value)
         | 
| 70 | 
            +
                    when TRUE_PATTERN
         | 
| 71 | 
            +
                      true
         | 
| 72 | 
            +
                    when FALSE_PATTERN
         | 
| 73 | 
            +
                      false
         | 
| 74 | 
            +
                    when ARRAY_PATTERN
         | 
| 75 | 
            +
                      value.split(/\s*,\s*/).map(&method(:convert_value))
         | 
| 76 | 
            +
                    when QUOTED_STRING_PATTERN
         | 
| 77 | 
            +
                      value.gsub(/(\A['"]|['"]\z)/, '')
         | 
| 78 | 
            +
                    else
         | 
| 79 | 
            +
                      value
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
            end
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # @api private
         | 
| 4 | 
            +
            # @since 0.5.0
         | 
| 5 | 
            +
            class Qonfig::Commands::LoadFromJSON < Qonfig::Commands::Base
         | 
| 6 | 
            +
              # @return [String]
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              # @api private
         | 
| 9 | 
            +
              # @since 0.5.0
         | 
| 10 | 
            +
              attr_reader :file_path
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              # @return [Boolean]
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              # @api private
         | 
| 15 | 
            +
              # @sicne 0.5.0
         | 
| 16 | 
            +
              attr_reader :strict
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              # @param file_path [String]
         | 
| 19 | 
            +
              # @option strict [Boolean]
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              # @api private
         | 
| 22 | 
            +
              # @since 0.5.0
         | 
| 23 | 
            +
              def initialize(file_path, strict: true)
         | 
| 24 | 
            +
                @file_path = file_path
         | 
| 25 | 
            +
                @strict = strict
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              # @param settings [Qonfig::Settings]
         | 
| 29 | 
            +
              # @return [void]
         | 
| 30 | 
            +
              #
         | 
| 31 | 
            +
              # @api private
         | 
| 32 | 
            +
              # @since 0.5.0
         | 
| 33 | 
            +
              def call(settings)
         | 
| 34 | 
            +
                json_data = Qonfig::Loaders::JSON.load_file(file_path, fail_on_unexist: strict)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                raise(
         | 
| 37 | 
            +
                  Qonfig::IncompatibleJSONStructureError,
         | 
| 38 | 
            +
                  'JSON object should have a hash-like structure'
         | 
| 39 | 
            +
                ) unless json_data.is_a?(Hash)
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                json_based_settings = build_data_set_class(json_data).new.settings
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                settings.__append_settings__(json_based_settings)
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              private
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              # @param json_data [Hash]
         | 
| 49 | 
            +
              # @return [Class<Qonfig::DataSet>]
         | 
| 50 | 
            +
              #
         | 
| 51 | 
            +
              # @api private
         | 
| 52 | 
            +
              # @since 0.5.0
         | 
| 53 | 
            +
              def build_data_set_class(json_data)
         | 
| 54 | 
            +
                Qonfig::DataSet::ClassBuilder.build_from_hash(json_data)
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| @@ -0,0 +1,73 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # @api private
         | 
| 4 | 
            +
            # @since 0.2.0
         | 
| 5 | 
            +
            class Qonfig::Commands::LoadFromSelf < Qonfig::Commands::Base
         | 
| 6 | 
            +
              # @return [String]
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              # @api private
         | 
| 9 | 
            +
              # @since 0.2.0
         | 
| 10 | 
            +
              attr_reader :caller_location
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              # @param caller_location [String]
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              # @api private
         | 
| 15 | 
            +
              # @since 0.2.0
         | 
| 16 | 
            +
              def initialize(caller_location)
         | 
| 17 | 
            +
                @caller_location = caller_location
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              # @param settings [Qonfig::Settings]
         | 
| 21 | 
            +
              # @return [void]
         | 
| 22 | 
            +
              #
         | 
| 23 | 
            +
              # @api private
         | 
| 24 | 
            +
              # @since 0.2.0
         | 
| 25 | 
            +
              def call(settings)
         | 
| 26 | 
            +
                yaml_data = load_self_placed_yaml_data
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                yaml_based_settings = build_data_set_klass(yaml_data).new.settings
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                settings.__append_settings__(yaml_based_settings)
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              private
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              # @return [Hash]
         | 
| 36 | 
            +
              #
         | 
| 37 | 
            +
              # @raise [Qonfig::SelfDataNotFound]
         | 
| 38 | 
            +
              # @raise [Qonfig::IncompatibleYAMLStructureError]
         | 
| 39 | 
            +
              #
         | 
| 40 | 
            +
              # @api private
         | 
| 41 | 
            +
              # @since 0.2.0
         | 
| 42 | 
            +
              def load_self_placed_yaml_data
         | 
| 43 | 
            +
                caller_file = caller_location.split(':').first
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                raise(
         | 
| 46 | 
            +
                  Qonfig::SelfDataNotFoundError,
         | 
| 47 | 
            +
                  "Caller file does not exist! (location: #{caller_location})"
         | 
| 48 | 
            +
                ) unless File.exist?(caller_file)
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                data_match = IO.read(caller_file).match(/\n__END__\n(?<end_data>.*)/m)
         | 
| 51 | 
            +
                raise Qonfig::SelfDataNotFoundError, '__END__ data not found!' unless data_match
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                end_data = data_match[:end_data]
         | 
| 54 | 
            +
                raise Qonfig::SelfDataNotFoundError, '__END__ data not found!' unless end_data
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                yaml_data = Qonfig::Loaders::YAML.load(end_data)
         | 
| 57 | 
            +
                raise(
         | 
| 58 | 
            +
                  Qonfig::IncompatibleYAMLStructureError,
         | 
| 59 | 
            +
                  'YAML content should have a hash-like structure'
         | 
| 60 | 
            +
                ) unless yaml_data.is_a?(Hash)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                yaml_data
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              # @param self_placed_yaml_data [Hash]
         | 
| 66 | 
            +
              # @return [Class<Qonfig::DataSet>]
         | 
| 67 | 
            +
              #
         | 
| 68 | 
            +
              # @api private
         | 
| 69 | 
            +
              # @since 0.2.0
         | 
| 70 | 
            +
              def build_data_set_klass(self_placed_yaml_data)
         | 
| 71 | 
            +
                Qonfig::DataSet::ClassBuilder.build_from_hash(self_placed_yaml_data)
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
            end
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # @api private
         | 
| 4 | 
            +
            # @since 0.2.0
         | 
| 5 | 
            +
            class Qonfig::Commands::LoadFromYAML < Qonfig::Commands::Base
         | 
| 6 | 
            +
              # @return [String]
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              # @api private
         | 
| 9 | 
            +
              # @since 0.2.0
         | 
| 10 | 
            +
              attr_reader :file_path
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              # @return [Boolean]
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              # @api private
         | 
| 15 | 
            +
              # @since 0.2.0
         | 
| 16 | 
            +
              attr_reader :strict
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              # @param file_path [String]
         | 
| 19 | 
            +
              # @option strict [Boolean]
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              # @api private
         | 
| 22 | 
            +
              # @since 0.2.0
         | 
| 23 | 
            +
              def initialize(file_path, strict: true)
         | 
| 24 | 
            +
                @file_path = file_path
         | 
| 25 | 
            +
                @strict = strict
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              # @param settings [Qonfig::Settings]
         | 
| 29 | 
            +
              # @return [void]
         | 
| 30 | 
            +
              #
         | 
| 31 | 
            +
              # @raise [Qonfig::IncompatibleYAMLStructureError]
         | 
| 32 | 
            +
              #
         | 
| 33 | 
            +
              # @api private
         | 
| 34 | 
            +
              # @since 0.2.0
         | 
| 35 | 
            +
              def call(settings)
         | 
| 36 | 
            +
                yaml_data = Qonfig::Loaders::YAML.load_file(file_path, fail_on_unexist: strict)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                raise(
         | 
| 39 | 
            +
                  Qonfig::IncompatibleYAMLStructureError,
         | 
| 40 | 
            +
                  'YAML content should have a hash-like structure'
         | 
| 41 | 
            +
                ) unless yaml_data.is_a?(Hash)
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                yaml_based_settings = build_data_set_class(yaml_data).new.settings
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                settings.__append_settings__(yaml_based_settings)
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              private
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              # @param yaml_data [Hash]
         | 
| 51 | 
            +
              # @return [Class<Qonfig::DataSet>]
         | 
| 52 | 
            +
              #
         | 
| 53 | 
            +
              # @api private
         | 
| 54 | 
            +
              # @since 0.2.0
         | 
| 55 | 
            +
              def build_data_set_class(yaml_data)
         | 
| 56 | 
            +
                Qonfig::DataSet::ClassBuilder.build_from_hash(yaml_data)
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| @@ -0,0 +1,116 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # @api public
         | 
| 4 | 
            +
            # @since 0.2.0
         | 
| 5 | 
            +
            module Qonfig::Configurable
         | 
| 6 | 
            +
              class << self
         | 
| 7 | 
            +
                # @param base_klass [Class]
         | 
| 8 | 
            +
                # @return [void]
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                # @api private
         | 
| 11 | 
            +
                # @since 0.2.0
         | 
| 12 | 
            +
                def included(base_klass)
         | 
| 13 | 
            +
                  base_klass.instance_variable_set(:@__qonfig_access_lock__, Mutex.new)
         | 
| 14 | 
            +
                  base_klass.instance_variable_set(:@__qonfig_definition_lock__, Mutex.new)
         | 
| 15 | 
            +
                  base_klass.instance_variable_set(:@__qonfig_config_klass__, Class.new(Qonfig::DataSet))
         | 
| 16 | 
            +
                  base_klass.instance_variable_set(:@__qonfig_config__, nil)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  base_klass.extend(ClassMethods)
         | 
| 19 | 
            +
                  base_klass.include(InstanceMethods)
         | 
| 20 | 
            +
                  base_klass.singleton_class.prepend(ClassInheritance)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  super
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              # @api private
         | 
| 27 | 
            +
              # @since 0.2.0
         | 
| 28 | 
            +
              module ClassInheritance
         | 
| 29 | 
            +
                # @param child_klass [Class]
         | 
| 30 | 
            +
                # @return [void]
         | 
| 31 | 
            +
                #
         | 
| 32 | 
            +
                # @api private
         | 
| 33 | 
            +
                # @since 0.2.0
         | 
| 34 | 
            +
                def inherited(child_klass)
         | 
| 35 | 
            +
                  inherited_config_klass = Class.new(@__qonfig_config_klass__)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  child_klass.instance_variable_set(:@__qonfig_definition_lock__, Mutex.new)
         | 
| 38 | 
            +
                  child_klass.instance_variable_set(:@__qonfig_access_lock__, Mutex.new)
         | 
| 39 | 
            +
                  child_klass.instance_variable_set(:@__qonfig_config_klass__, inherited_config_klass)
         | 
| 40 | 
            +
                  child_klass.instance_variable_set(:@__qonfig_config__, nil)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  super
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              # @api private
         | 
| 47 | 
            +
              # @since 0.2.0
         | 
| 48 | 
            +
              module ClassMethods
         | 
| 49 | 
            +
                # @param block [Proc]
         | 
| 50 | 
            +
                # @return [void]
         | 
| 51 | 
            +
                #
         | 
| 52 | 
            +
                # @api public
         | 
| 53 | 
            +
                # @since 0.2.0
         | 
| 54 | 
            +
                def configuration(&block)
         | 
| 55 | 
            +
                  @__qonfig_definition_lock__.synchronize do
         | 
| 56 | 
            +
                    @__qonfig_config_klass__.instance_eval(&block) if block_given?
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                # @param options_map [Hash]
         | 
| 61 | 
            +
                # @param block [Proc]
         | 
| 62 | 
            +
                # @return [void]
         | 
| 63 | 
            +
                #
         | 
| 64 | 
            +
                # @api public
         | 
| 65 | 
            +
                # @since 0.2.0
         | 
| 66 | 
            +
                def configure(options_map = {}, &block)
         | 
| 67 | 
            +
                  @__qonfig_access_lock__.synchronize do
         | 
| 68 | 
            +
                    config.configure(options_map, &block)
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                # @return [Qonfig::DataSet]
         | 
| 73 | 
            +
                #
         | 
| 74 | 
            +
                # @api public
         | 
| 75 | 
            +
                # @since 0.2.0
         | 
| 76 | 
            +
                def config
         | 
| 77 | 
            +
                  @__qonfig_definition_lock__.synchronize do
         | 
| 78 | 
            +
                    @__qonfig_config__ ||= @__qonfig_config_klass__.new
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              # @api private
         | 
| 84 | 
            +
              # @since 0.2.0
         | 
| 85 | 
            +
              module InstanceMethods
         | 
| 86 | 
            +
                # @return [Qonfig::DataSet]
         | 
| 87 | 
            +
                #
         | 
| 88 | 
            +
                # @api public
         | 
| 89 | 
            +
                # @since 0.2.0
         | 
| 90 | 
            +
                def config
         | 
| 91 | 
            +
                  self.class.instance_variable_get(:@__qonfig_definition_lock__).synchronize do
         | 
| 92 | 
            +
                    @__qonfig_config__ ||= self.class.instance_variable_get(:@__qonfig_config_klass__).new
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                # @return [Qonfig::DataSet]
         | 
| 97 | 
            +
                #
         | 
| 98 | 
            +
                # @api public
         | 
| 99 | 
            +
                # @since 0.6.0
         | 
| 100 | 
            +
                def shared_config
         | 
| 101 | 
            +
                  self.class.config
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                # @param options_map [Hash]
         | 
| 105 | 
            +
                # @param block [Proc]
         | 
| 106 | 
            +
                # @return [void]
         | 
| 107 | 
            +
                #
         | 
| 108 | 
            +
                # @api public
         | 
| 109 | 
            +
                # @since 0.2.0
         | 
| 110 | 
            +
                def configure(options_map = {}, &block)
         | 
| 111 | 
            +
                  self.class.instance_variable_get(:@__qonfig_access_lock__).synchronize do
         | 
| 112 | 
            +
                    config.configure(options_map, &block)
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
              end
         | 
| 116 | 
            +
            end
         |