File: settings.rb

package info (click to toggle)
ruby-dry-configurable 0.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 184 kB
  • sloc: ruby: 397; makefile: 4
file content (117 lines) | stat: -rw-r--r-- 2,509 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
require 'set'
require 'concurrent/array'
require 'dry/configurable/settings/argument_parser'
require 'dry/configurable/setting'
require 'dry/configurable/config'

module Dry
  module Configurable
    # A collection of settings. This is not part of the public API.
    #
    # @private
    class Settings
      Parser = ArgumentParser.new.freeze

      class DSL
        def self.call(&block)
          new.instance_exec do
            instance_exec(&block)
            @settings
          end
        end

        def initialize
          @settings = Settings.new
        end

        def setting(*args, &block)
          @settings.add(*args, &block)
        end
      end

      # Capture nested config definition
      #
      # @return [Dry::Configurable::Setting]
      def self.capture(&block)
        DSL.(&block)
      end

      attr_reader :settings

      attr_reader :config_class

      attr_reader :index
      private :index

      def initialize(settings = ::Concurrent::Array.new)
        @settings = settings
        @config_class = Config[self]
        @index = settings.map { |s| [s.name, s] }.to_h
        yield(self) if block_given?
      end

      def add(key, value = Undefined, options = Undefined, &block)
        extended = singleton_class < Configurable
        raise_already_defined_config(key) if extended && configured?

        *args, opts = Parser.(value, options, block)

        Setting.new(key, *args, { **opts, reserved: reserved?(key) }).tap do |s|
          settings.delete_if { |e| e.name.eql?(s.name) }
          settings << s
          index[s.name] = s
          @names = nil
        end
      end

      def each
        settings.each { |s| yield(s) }
      end

      def names
        @names ||= index.keys.to_set
      end

      def [](name)
        index[name]
      end

      def empty?
        settings.empty?
      end

      def name?(name)
        index.key?(name)
      end

      def dup
        Settings.new(settings.dup)
      end

      def freeze
        settings.freeze
        super
      end

      def create_config
        config_class.new
      end

      def config_defined?
        config_class.config_defined?
      end

      def reserved?(name)
        reserved_names.include?(name)
      end

      def reserved_names
        @reserved_names ||= [
          config_class.instance_methods(false),
          config_class.superclass.instance_methods(false),
          %i(class public_send)
        ].reduce(:+)
      end
    end
  end
end