Class: Dry::Config::Base

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/dry/config/base.rb

Overview

If this behavior of merging arrays or the defaults are somehow un-sensible, file an issue and we’ll revisit it.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Base

Returns a new instance of Base.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/dry/config/base.rb', line 24

def initialize(options = {})
  @options = {
      env: ENV,                  # default to ENV for interpolation
      interpolation: true,       # interpolate string contents on read with given ENV
      symbolize: true,           # provide symbol based key access for everything
      unsymbolize_to_yaml: true, # on to_yaml or write_yaml_file unsymbolize keys
      default_configuration: {}, # seed configuration
      prune: [:development, :test, :staging, :production] # used for pruning (optional)
  }.merge options

  @default_configuration = @options[:default_configuration]

  # (optional) used for pruning initial base set.  See #resolve_config
  @prune = @options[:prune]

  # setup a default configuration
  clear
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



160
161
162
163
164
# File 'lib/dry/config/base.rb', line 160

def method_missing(name, *args, &block)
  @configuration[name.to_sym] ||
      #fail(NoMethodError, "Unknown settings root \'#{name}\'", caller)
      nil
end

Instance Attribute Details

#configurationObject (readonly)

Returns the value of attribute configuration.



16
17
18
# File 'lib/dry/config/base.rb', line 16

def configuration
  @configuration
end

#environmentObject (readonly)

Returns the value of attribute environment.



17
18
19
# File 'lib/dry/config/base.rb', line 17

def environment
  @environment
end

#filenamesObject (readonly)

Returns the value of attribute filenames.



18
19
20
# File 'lib/dry/config/base.rb', line 18

def filenames
  @filenames
end

Instance Method Details

#[](key) ⇒ Object

configuration hash delegation with option based symbolization



167
168
169
170
# File 'lib/dry/config/base.rb', line 167

def [] key
  key = key.to_sym if symbolize?
  @configuration[key]
end

#[]=(key, value) ⇒ Object

configuration hash delegation with option based symbolization



173
174
175
176
# File 'lib/dry/config/base.rb', line 173

def []=(key, value)
  key = key.to_sym if symbolize?
  @configuration[key] = value
end

#clearObject



154
155
156
157
158
# File 'lib/dry/config/base.rb', line 154

def clear
  # clone a copy of the default
  @configuration = {}.merge @default_configuration
  @configuration.deep_symbolize if symbolize?
end

#include?(key) ⇒ Boolean

configuration hash delegation with option based symbolization

Returns:

  • (Boolean)


179
180
181
182
# File 'lib/dry/config/base.rb', line 179

def include?(key)
  key = key.to_sym if symbolize?
  @configuration.include? key
end

#interpolate?Boolean

Returns:

  • (Boolean)


192
193
194
# File 'lib/dry/config/base.rb', line 192

def interpolate?
  @options[:interpolation]
end

#load!(environment, *filenames) ⇒ Object

Load the configuration and save state.

We call #load! and provide a name of the file to read as it’s argument. We can also pass in some options, but at the moment it’s being used to allow per-environment overrides in Rails



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/dry/config/base.rb', line 48

def load!(environment, *filenames)

  # save these in case we #reload
  @environment = environment
  @filenames = filenames

  # load the configuration
  @configuration = load_unpruned(environment, *filenames)

  # Prune all known environments so that we end up with the top-level configuration.
  @prune.each do |env|
    @configuration.delete(env)
  end
end

#load_unpruned(environment, *filenames) ⇒ Object

Load the configuration without saving state. Useful for validation of complex configuration resolution without

altering the existing state.


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/dry/config/base.rb', line 65

def load_unpruned(environment, *filenames)

  # raise 'Unspecified environment' if environment.nil?
  raise 'Unspecified filename' if filenames.nil?

  # ensure symbol if symbolize?
  environment = environment.to_sym if symbolize? && !environment.nil?

  # get a clone of the current configuration
  config = {}.merge @configuration

  filenames.each do |filename|
    # merge all top level settings with the defaults set in the #init
    config.deeper_merge! resolve_config(environment, filename)
  end

  config
end

#load_yaml_file(filename) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/dry/config/base.rb', line 104

def load_yaml_file(filename)

  # without interpolation
  # config = Psych.load_file(filename)

  # get file contents as string
  file = File.open(filename, 'r:bom|utf-8')
  contents = file.read

  env = @options[:env]
  if interpolate?
    # interpolate/substitute/expand ENV variables with the string contents before parsing
    # bash - $VAR
    contents = contents.gsub(/\$(\w+)/) { env[$1] }
    # bash - ${VAR}
    contents = contents.gsub(/\${(\w+)}/) { env[$1] }
    # bash - ~ is env['HOME']
    contents = contents.gsub(/(~)/) { env['HOME'] }
    # ruby - #{VAR}
    contents = contents.gsub(/\#{(\w+)}/) { env[$1] }
  end
  # now parse
  config = Psych.load(contents, filename)

  raise "Failed to load #{filename}" if config.nil?
  config = config.deep_symbolize if symbolize?
  config
end

#reload!Object



149
150
151
152
# File 'lib/dry/config/base.rb', line 149

def reload!
  clear
  load! @environment, @filenames
end

#resolve_config(environment, filename) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/dry/config/base.rb', line 84

def resolve_config(environment, filename)
  config = load_yaml_file(filename)

  should_overlay_environment = environment && config[environment]

  # overlay the specific environment if provided
  if should_overlay_environment
    # re-read the file
    environment_settings = load_yaml_file(filename)

    # snag the requested environment
    environment_settings = environment_settings[environment.to_sym]

    # finally overlay what was provided the settings from the specific environment
    config.deeper_merge! environment_settings
  end

  config
end

#symbolize?Boolean

Returns:

  • (Boolean)


184
185
186
# File 'lib/dry/config/base.rb', line 184

def symbolize?
  @options[:symbolize]
end

#to_yaml(config = @configuration) ⇒ Object



133
134
135
136
137
138
139
140
141
# File 'lib/dry/config/base.rb', line 133

def to_yaml(config = @configuration)
  if unsymbolize_to_yaml?
    config = config.dup.deep_symbolize(true)
  else
    config = @configuration
  end

  Psych.dump(config)
end

#unsymbolize_to_yaml?Boolean

Returns:

  • (Boolean)


188
189
190
# File 'lib/dry/config/base.rb', line 188

def unsymbolize_to_yaml?
  @options[:unsymbolize_to_yaml]
end

#write_yaml_file(filename, config = @configuration) ⇒ Object



143
144
145
146
147
# File 'lib/dry/config/base.rb', line 143

def write_yaml_file(filename, config = @configuration)
  File.open(filename, 'w') do |file|
    file.write(to_yaml(config))
  end
end