lib/dry/configurable/setting.rb
# frozen_string_literal: true require 'set' require 'dry/equalizer' require 'dry/configurable/constants' require 'dry/configurable/config' module Dry module Configurable # This class represents a setting and is used internally. # # @api private class Setting include Dry::Equalizer(:name, :value, :options, inspect: false) OPTIONS = %i[input default reader constructor settings].freeze DEFAULT_CONSTRUCTOR = -> v { v }.freeze CLONABLE_VALUE_TYPES = [Array, Hash, Set, Config].freeze # @api private attr_reader :name # @api private attr_reader :writer_name # @api private attr_reader :input # @api private attr_reader :default # @api private attr_reader :options # Specialized Setting which includes nested settings # # @api private class Nested < Setting CONSTRUCTOR = Config.method(:new) # @api private def pristine with(input: input.pristine) end # @api private def constructor CONSTRUCTOR end end # @api private def initialize(name, input: Undefined, default: Undefined, **options) @name = name @writer_name = :"#{name}=" @input = input.equal?(Undefined) ? default : input @default = default @options = options evaluate if input_defined? end # @api private def input_defined? !input.equal?(Undefined) end # @api private def value @value ||= evaluate end # @api private def evaluated? instance_variable_defined?(:@value) end # @api private def nested(settings) Nested.new(name, input: settings, **options) end # @api private def pristine with(input: Undefined) end # @api private def with(new_opts) self.class.new(name, input: input, default: default, **options, **new_opts) end # @api private def constructor options[:constructor] || DEFAULT_CONSTRUCTOR end # @api private def reader? options[:reader].equal?(true) end # @api private def writer?(meth) writer_name.equal?(meth) end # @api private def clonable_value? CLONABLE_VALUE_TYPES.any? { |type| value.is_a?(type) } end private # @api private def initialize_copy(source) super @value = source.value.dup if source.input_defined? && source.clonable_value? @options = source.options.dup end # @api private def evaluate @value = constructor[input.equal?(Undefined) ? nil : input] end end end end