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.0'

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeLoadableConfig

Returns a new instance of LoadableConfig.



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
118
119
120
121
122
# File 'lib/loadable_config.rb', line 68

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, [], [], 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

  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|
    value = config[attr.name]
    if attr.serializer
      value = attr.serializer.load(value)
    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



45
46
47
# File 'lib/loadable_config.rb', line 45

def _configuration
  @@_configuration
end

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



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

def attribute(attr, type: :string, schema: {}, optional: false, serializer: 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.kind_of?(Array)
  type.map! { |t| t.to_s }

  _attributes << Attribute.new(attr.to_s, type, schema, optional, serializer)
  attr_accessor attr
  define_singleton_method(attr) { instance.send(attr) }
end

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



39
40
41
42
43
# File 'lib/loadable_config.rb', line 39

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



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

def config_file(path)
  @_config_file = path
end

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

Yields:



49
50
51
52
53
54
55
# File 'lib/loadable_config.rb', line 49

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
# File 'lib/loadable_config.rb', line 15

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