lib/runger/config.rb in runger_config-4.0.0 vs lib/runger/config.rb in runger_config-5.0.0

- old
+ new

@@ -1,10 +1,10 @@ # frozen_string_literal: true -require "active_support/all" -require "runger/optparse_config" -require "runger/dynamic_config" +require 'active_support/all' +require 'runger/dynamic_config' +require 'runger/optparse_config' module Runger # :nodoc: using Runger::Ext::DeepDup using Runger::Ext::DeepFreeze using Runger::Ext::Hash @@ -18,10 +18,12 @@ # Base config class # Provides `attr_config` method to describe # configuration parameters and set defaults class Config + include OptparseConfig + include DynamicConfig PARAM_NAME = /^[a-z_](\w+)?$/ # List of names that couldn't be used as config names # (the class instance methods we use) RESERVED_NAMES = %i[ @@ -51,13 +53,10 @@ class Error < StandardError; end class ValidationError < Error; end - include OptparseConfig - include DynamicConfig - class BlockCallback attr_reader :block def initialize(block) @block = block @@ -81,77 +80,88 @@ class << self def attr_config(*args, **hargs) new_defaults = hargs.deep_dup new_defaults.stringify_keys! - defaults.merge! new_defaults + defaults.merge!(new_defaults) new_keys = ((args + new_defaults.keys) - config_attributes) - validate_param_names! new_keys.map(&:to_s) + validate_param_names!(new_keys.map(&:to_s)) new_keys.map!(&:to_sym) unless (reserved_names = (new_keys & RESERVED_NAMES)).empty? - raise ArgumentError, "Can not use the following reserved names as config attrubutes: " \ - "#{reserved_names.sort.map(&:to_s).join(", ")}" + raise(ArgumentError, + 'Can not use the following reserved names as config attrubutes: ' \ + "#{reserved_names.sort.map(&:to_s).join(', ')}") end config_attributes.push(*new_keys) define_config_accessor(*new_keys) # Define predicate methods ("param?") for attributes # having `true` or `false` as default values new_defaults.each do |key, val| next unless val.is_a?(TrueClass) || val.is_a?(FalseClass) - alias_method :"#{key}?", :"#{key}" + + alias_method(:"#{key}?", :"#{key}") end end def defaults return @defaults if instance_variable_defined?(:@defaults) - @defaults = if superclass < Runger::Config - superclass.defaults.deep_dup - else - new_empty_config - end + @defaults = + if superclass < Runger::Config + superclass.defaults.deep_dup + else + new_empty_config + end end def config_attributes return @config_attributes if instance_variable_defined?(:@config_attributes) - @config_attributes = if superclass < Runger::Config - superclass.config_attributes.dup - else - [] - end + @config_attributes = + if superclass < Runger::Config + superclass.config_attributes.dup + else + [] + end end def required(*names, env: nil, **nested) unknown_names = names + nested.keys - config_attributes - raise ArgumentError, "Unknown config param: #{unknown_names.join(",")}" if unknown_names.any? + if unknown_names.any? + raise(ArgumentError, + "Unknown config param: #{unknown_names.join(',')}") + end return unless Settings.matching_env?(env) required_attributes.push(*names) required_attributes.push(*nested.flatten_names) end def required_attributes return @required_attributes if instance_variable_defined?(:@required_attributes) - @required_attributes = if superclass < Runger::Config - superclass.required_attributes.dup - else - [] - end + @required_attributes = + if superclass < Runger::Config + superclass.required_attributes.dup + else + [] + end end def on_load(*names, &block) - raise ArgumentError, "Either methods or block should be specified, not both" if block && !names.empty? + if block && !names.empty? + raise(ArgumentError, + 'Either methods or block should be specified, not both') + end if block load_callbacks << BlockCallback.new(block) else load_callbacks.push(*names.map { NamedCallback.new(_1) }) @@ -159,15 +169,16 @@ end def load_callbacks return @load_callbacks if instance_variable_defined?(:@load_callbacks) - @load_callbacks = if superclass <= Runger::Config - superclass.load_callbacks.dup - else - [] - end + @load_callbacks = + if superclass <= Runger::Config + superclass.load_callbacks.dup + else + [] + end end def config_name(val = nil) return (@explicit_config_name = val.to_s) unless val.nil? @@ -190,50 +201,53 @@ def env_prefix(val = nil) return (@env_prefix = val.to_s.upcase) unless val.nil? return @env_prefix if instance_variable_defined?(:@env_prefix) - @env_prefix = if superclass < Runger::Config && superclass.explicit_config_name? - superclass.env_prefix - else - config_name.upcase - end + @env_prefix = + if superclass < Runger::Config && superclass.explicit_config_name? + superclass.env_prefix + else + config_name.upcase + end end def loader_options(val = nil) return (@loader_options = val) unless val.nil? return @loader_options if instance_variable_defined?(:@loader_options) - @loader_options = if superclass < Runger::Config - superclass.loader_options - else - {} - end + @loader_options = + if superclass < Runger::Config + superclass.loader_options + else + {} + end end def new_empty_config = {} def coerce_types(mapping) - Utils.deep_merge!(coercion_mapping, mapping) + ::Runger::Utils.deep_merge!(coercion_mapping, mapping) mapping.each do |key, val| type = val.is_a?(::Hash) ? val[:type] : val next if type != :boolean - alias_method :"#{key}?", :"#{key}" + alias_method(:"#{key}?", :"#{key}") end end def coercion_mapping return @coercion_mapping if instance_variable_defined?(:@coercion_mapping) - @coercion_mapping = if superclass < Runger::Config - superclass.coercion_mapping.deep_dup - else - {} - end + @coercion_mapping = + if superclass < Runger::Config + superclass.coercion_mapping.deep_dup + else + {} + end end def type_caster(val = nil) return @type_caster unless val.nil? @@ -248,26 +262,27 @@ def fallback_type_caster(val = nil) return (@fallback_type_caster = val) unless val.nil? return @fallback_type_caster if instance_variable_defined?(:@fallback_type_caster) - @fallback_type_caster = if superclass < Runger::Config - superclass.fallback_type_caster.deep_dup - else - ::Runger::AutoCast - end + @fallback_type_caster = + if superclass < Runger::Config + superclass.fallback_type_caster.deep_dup + else + ::Runger::AutoCast + end end def disable_auto_cast! @fallback_type_caster = ::Runger::NoCast end private def define_config_accessor(*names) names.each do |name| - accessors_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1 + accessors_module.module_eval(<<~RUBY, __FILE__, __LINE__ + 1) def #{name}=(val) __trace__&.record_value(val, "#{name}", **Tracing.current_trace_source) values[:#{name}] = val end @@ -279,35 +294,37 @@ end def accessors_module return @accessors_module if instance_variable_defined?(:@accessors_module) - @accessors_module = Module.new.tap do |mod| - include mod - end + @accessors_module = + Module.new.tap do |mod| + include mod + end end def build_config_name unless name - raise "Please, specify config name explicitly for anonymous class " \ - "via `config_name :my_config`" + raise('Please, specify config name explicitly for anonymous class ' \ + 'via `config_name :my_config`') end - unless name.underscore.gsub("/", "_") =~ /(\w+)_config\z/ - raise "Couldn't infer config name, please, specify it explicitly " \ - "via `config_name :my_config`" + unless name.underscore.tr('/', '_') =~ /(\w+)_config\z/ + raise("Couldn't infer config name, please, specify it explicitly " \ + 'via `config_name :my_config`') end - Regexp.last_match[1].delete_suffix("_config").tap(&:downcase!) + Regexp.last_match[1].delete_suffix('_config').tap(&:downcase!) end def validate_param_names!(names) - invalid_names = names.reject { |name| name =~ PARAM_NAME } + invalid_names = names.grep_v(PARAM_NAME) return if invalid_names.empty? - raise ArgumentError, "Invalid attr_config name: #{invalid_names.join(", ")}.\n" \ - "Valid names must satisfy /#{PARAM_NAME.source}/." + raise(ArgumentError, + "Invalid attr_config name: #{invalid_names.join(', ')}.\n" \ + "Valid names must satisfy /#{PARAM_NAME.source}/.") end end on_load :validate_required_attributes! @@ -323,11 +340,11 @@ # my_config = Runger::Config.new({some: :value}) # def initialize(overrides = nil) @config_name = self.class.config_name - raise ArgumentError, "Config name is missing" unless @config_name + raise(ArgumentError, 'Config name is missing') unless @config_name @env_prefix = self.class.env_prefix @values = {} load(overrides) @@ -346,29 +363,30 @@ end def load(overrides = nil) base_config = self.class.defaults.deep_dup - trace = Tracing.capture do - Tracing.trace!(:defaults) { base_config } + trace = + Tracing.capture do + Tracing.trace!(:defaults) { base_config } - config_path = resolve_config_path(config_name, env_prefix) + config_path = resolve_config_path(config_name, env_prefix) - load_from_sources( - base_config, - name: config_name, - env_prefix:, - config_path:, - **self.class.loader_options - ) + load_from_sources( + base_config, + name: config_name, + env_prefix:, + config_path:, + **self.class.loader_options, + ) - if overrides - Tracing.trace!(:load) { overrides } + if overrides + Tracing.trace!(:load) { overrides } - Utils.deep_merge!(base_config, overrides) + ::Runger::Utils.deep_merge!(base_config, overrides) + end end - end base_config.each do |key, val| write_config_attr(key.to_sym, val) end @@ -383,13 +401,13 @@ @__trace__ = trace self end - def load_from_sources(base_config, **) + def load_from_sources(base_config, **options) Runger.loaders.each do |(_id, loader)| - Utils.deep_merge!(base_config, loader.call(**)) + ::Runger::Utils.deep_merge!(base_config, loader.call(**options)) end base_config end def dig(*) = values.dig(*) @@ -404,32 +422,33 @@ new_config.instance_variable_set(:@values, values.deep_dup) end end def resolve_config_path(name, env_prefix) - Runger.env.fetch(env_prefix).delete("conf") || Settings.default_config_path.call(name) + Runger.env.fetch(env_prefix).delete('conf') || Settings.default_config_path.call(name) end def deconstruct_keys(keys) = values.deconstruct_keys(keys) def to_source_trace = __trace__&.to_h def inspect - "#<#{self.class}:0x#{vm_object_id.rjust(16, "0")} config_name=\"#{config_name}\" env_prefix=\"#{env_prefix}\" " \ - "values=#{values.inspect}>" + "#<#{self.class}:0x#{vm_object_id.rjust(16, + '0')} config_name=\"#{config_name}\" env_prefix=\"#{env_prefix}\" " \ + "values=#{values.inspect}>" end def pretty_print(q) - q.object_group self do + q.object_group(self) do q.nest(1) do q.breakable q.text "config_name=#{config_name.inspect}" q.breakable q.text "env_prefix=#{env_prefix.inspect}" q.breakable - q.text "values:" - q.pp __trace__ + q.text 'values:' + q.pp(__trace__) end end end def as_env @@ -440,15 +459,16 @@ attr_reader :values, :__trace__ def validate_required_attributes! self.class.required_attributes.select do |name| - val = values.dig(*name.to_s.split(".").map(&:to_sym)) + val = values.dig(*name.to_s.split('.').map(&:to_sym)) val.nil? || (val.is_a?(String) && val.empty?) end.then do |missing| next if missing.empty? - raise_validation_error "The following config parameters for `#{self.class.name}(config_name: #{self.class.config_name})` are missing or empty: #{missing.join(", ")}" + + raise_validation_error("The following config parameters for `#{self.class.name}(config_name: #{self.class.config_name})` are missing or empty: #{missing.join(', ')}") end end def write_config_attr(key, val) key = key.to_sym @@ -457,10 +477,10 @@ val = __type_caster__.coerce(key, val) public_send(:"#{key}=", val) end def raise_validation_error(msg) - raise ValidationError, msg + raise(ValidationError, msg) end def __type_caster__ self.class.type_caster end