Class: LoadableConfig

Inherits:
Object
  • Object
show all
Defined in:
lib/loadable_config.rb,
lib/loadable_config/version.rb

Defined Under Namespace

Classes: Attribute, Options

Constant Summary collapse

ATTRIBUTE_BLACKLIST =
Set.new(self.methods - Object.instance_methods)
VERSION =
'1.0.4'

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLoadableConfig

Returns a new instance of LoadableConfig.



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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/loadable_config.rb', line 71

def initialize
  if self.class._config_file.nil? || self.class._config_file.empty?
    raise RuntimeError.new("Incomplete LoadableConfig '#{self.class.name}': config_file not set")
  end

  config_file_path = self.class._config_file

  if (prefix = LoadableConfig._configuration.config_path_prefix)
    config_file_path = File.join(prefix, config_file_path)
  end

  unless File.exist?(config_file_path)
    raise RuntimeError.new("Cannot configure #{self.class.name}: "\
                           "configuration file '#{config_file_path}' missing")
  end

  config_data = File.read(config_file_path)

  if (preprocessor = LoadableConfig._configuration.preprocessor)
    config_data = preprocessor.call(config_data)
  end

  config = YAML.safe_load(config_data, aliases: true)
  unless config
    raise RuntimeError.new("Cannot configure #{self.class.name}: "\
                           "Configuration file empty for #{self.class.name}.")
  end

  if (env = LoadableConfig._configuration.environment_key)
    config = config.fetch(env) do
      raise RuntimeError.new("Cannot configure #{self.class.name}: "\
                             "Configuration missing for environment '#{env}'")
    end
  end

  if (overlay_function = LoadableConfig._configuration.overlay_function)
    overlay_data = overlay_function.call(self.class)
    config = _deep_merge(config, overlay_data) if overlay_data
  end

  unless config
    raise RuntimeError.new("Configuration file missing config for #{self.class.name}.")
  end

  valid, errors = _schema.validate(config)
  unless valid
    raise ArgumentError.new("Errors parsing #{self.class.name}:\n" +
                            errors.map { |e| "#{e.pointer}: #{e.message}" }.join("\n"))
  end

  self.class._attributes.each do |attr|
    if config.has_key?(attr.name)
      value = config[attr.name]
      if attr.serializer
        value = attr.serializer.load(value)
      end
    else
      value = attr.default
    end

    self.public_send(:"#{attr.name}=", value)
  end

  self.freeze
end

Class Attribute Details

._attributesObject (readonly)

Returns the value of attribute _attributes.



13
14
15
# File 'lib/loadable_config.rb', line 13

def _attributes
  @_attributes
end

._config_fileObject (readonly)

Returns the value of attribute _config_file.



13
14
15
# File 'lib/loadable_config.rb', line 13

def _config_file
  @_config_file
end

Class Method Details

._configurationObject



47
48
49
# File 'lib/loadable_config.rb', line 47

def _configuration
  @@_configuration
end

.attribute(attr, type: :string, schema: {}, serializer: nil, default: nil, optional: !default.nil?)) ⇒ Object



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

def attribute(attr, type: :string, schema: {}, serializer: nil, default: nil, optional: !default.nil?)
  @_attributes ||= []
  attr = attr.to_sym
  if ATTRIBUTE_BLACKLIST.include?(attr)
    raise ArgumentError.new("Illegal attribute name '#{attr}': "\
                            'attributes must not collide with class methods of LoadableConfig')
  end

  type = [type] unless type.is_a?(Array)
  type.map! { |t| t.to_s }

  _attributes << Attribute.new(attr.to_s, type, schema, optional, serializer, default)
  attr_accessor attr

  define_singleton_method(attr) { instance.send(attr) }
end

.attributes(*attrs, type: :string, optional: false, serializer: nil) ⇒ Object



41
42
43
44
45
# File 'lib/loadable_config.rb', line 41

def attributes(*attrs, type: :string, optional: false, serializer: nil)
  attrs.each do |attr|
    attribute(attr, type: type, optional: optional, serializer: serializer)
  end
end

.config_file(path) ⇒ Object



20
21
22
# File 'lib/loadable_config.rb', line 20

def config_file(path)
  @_config_file = path
end

.configure! {|@@_configuration| ... } ⇒ Object

Yields:



51
52
53
54
55
56
57
58
# File 'lib/loadable_config.rb', line 51

def configure!
  if @@_configuration.frozen?
    raise ArgumentError.new('Cannot configure LoadableConfig: already configured')
  end

  yield(@@_configuration)
  @@_configuration.freeze
end

.inherited(subclass) ⇒ Object



15
16
17
18
# File 'lib/loadable_config.rb', line 15

def inherited(subclass)
  super
  subclass.send(:include, Singleton)
end