Class: Attributor::Flatpack::Config

Inherits:
Hash
  • Object
show all
Defined in:
lib/attributor/flatpack/config.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data = nil) ⇒ Config

Returns a new instance of Config.



37
38
39
40
41
42
43
44
# File 'lib/attributor/flatpack/config.rb', line 37

def initialize(data = nil)
  @raw = data
  @contents = {}

  self.class.keys.each do |k, _v|
    self.define_accessors(k)
  end
end

Class Method Details

.example(context = nil, **values) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/attributor/flatpack/config.rb', line 29

def self.example(context = nil, **values)
  example = super
  # Need the @raw to be set as well, since we're using it in fetch
  contents = example.instance_variable_get(:@contents)
  example.instance_variable_set(:@raw, contents.dup)
  example
end

.from_hash(object, _context, **_opts) ⇒ Object



24
25
26
27
# File 'lib/attributor/flatpack/config.rb', line 24

def self.from_hash(object, _context, **_opts)
  config = new(object)
  config
end

.inherited(klass) ⇒ Object



15
16
17
18
19
20
21
22
# File 'lib/attributor/flatpack/config.rb', line 15

def self.inherited(klass)
  super
  sep = self.separator
  klass.instance_eval do
    @separator = sep
  end
  klass.options[:dsl_compiler] = ConfigDSLCompiler
end

.separator(sep = nil) ⇒ Object



8
9
10
11
12
# File 'lib/attributor/flatpack/config.rb', line 8

def separator(sep = nil)
  return @separator unless sep

  @separator = sep
end

Instance Method Details

#[](key) ⇒ Object



131
132
133
# File 'lib/attributor/flatpack/config.rb', line 131

def [](key)
  get key
end

#[]=(key, val) ⇒ Object



135
136
137
# File 'lib/attributor/flatpack/config.rb', line 135

def []=(key, val)
  set key, val
end

#_get(key, attribute:, context:) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/attributor/flatpack/config.rb', line 82

def _get(key, attribute:, context:)
  if attribute.type < Attributor::Flatpack::Config
    top = fetch(key) do
      {}
    end
    attribute.load(top, context).merge!(subselect(key))
  else
    value = fetch(key) do
      # raise "couldn't find #{key.inspect} anywhere"
      nil
    end
    attribute.load(value, context)
  end
end

#default_context(key) ⇒ Object



72
73
74
# File 'lib/attributor/flatpack/config.rb', line 72

def default_context(key)
  generate_subcontext(Attributor::DEFAULT_ROOT_CONTEXT, key)
end

#define_accessors(name) ⇒ Object



46
47
48
49
# File 'lib/attributor/flatpack/config.rb', line 46

def define_accessors(name)
  define_reader(name)
  define_writer(name)
end

#define_reader(name) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/attributor/flatpack/config.rb', line 51

def define_reader(name)
  context = default_context(name)
  define_singleton_method(name) do
    get(name, context: context)
  end

  attribute = self.class.keys[name]
  return unless attribute.type == Attributor::Boolean

  define_singleton_method(name.to_s + '?') do
    !!get(name, attribute: attribute, context: context)
  end
end

#define_writer(name) ⇒ Object



65
66
67
68
69
70
# File 'lib/attributor/flatpack/config.rb', line 65

def define_writer(name)
  context = ['assignment', "of(#{name})"].freeze
  define_singleton_method(name.to_s + '=') do |value|
    set(name, value, context: context)
  end
end

#dump(**opts) ⇒ Object



180
181
182
183
184
# File 'lib/attributor/flatpack/config.rb', line 180

def dump(**opts)
  # quick hack to ensure we load all the values into @contents
  self.validate
  super
end

#fetch(key) ⇒ Object

search @raw for key



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/attributor/flatpack/config.rb', line 108

def fetch(key)
  return @raw[key] if @raw.key?(key)

  found_key, found_value = @raw.find do |(k, _v)|
    k.to_s.casecmp(key.to_s).zero?
  end

  return found_value if found_key

  yield if block_given?
end

#get(key, context: default_context(key), attribute: ) ⇒ Object

Raises:



76
77
78
79
80
# File 'lib/attributor/flatpack/config.rb', line 76

def get(key, context: default_context(key), attribute: self.class.keys[key])
  raise UndefinedKey.new(key, context) unless attribute

  @contents[key] ||= _get(key, attribute: attribute, context: context)
end

#merge!(other) ⇒ Object



139
140
141
142
143
144
145
146
# File 'lib/attributor/flatpack/config.rb', line 139

def merge!(other)
  # Not sure if we need to nuke the memozied set of loaded stuff here
  # or not... but it sounds like a good idea.
  @contents = {}
  @raw.merge!(other)

  self
end

#pretty_print(context: []) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
# File 'lib/attributor/flatpack/config.rb', line 168

def pretty_print(context: [])
  self.collect do |k, v|
    sub_context = context + [k]
    case v
    when Attributor::Flatpack::Config
      v.pretty_print(context: context | [k])
    else
      "#{sub_context.join('.')}=#{v.inspect}"
    end
  end.flatten
end

#set(key, value, context: default_context(key)) ⇒ Object



97
98
99
100
101
102
103
104
105
# File 'lib/attributor/flatpack/config.rb', line 97

def set(key, value, context: default_context(key))
  attribute = self.class.keys.fetch key do
    raise UndefinedKey.new(key, [key])
  end

  loaded = attribute.load(value, context)
  @contents[key] = loaded
  @raw[key] = loaded
end

#subselect(prefix) ⇒ Object



120
121
122
123
124
125
126
127
128
129
# File 'lib/attributor/flatpack/config.rb', line 120

def subselect(prefix)
  prefix_match = /^#{prefix.to_s}#{self.class.separator}?(.*)/i

  selected = @raw.collect do |(k, v)|
    if (match = prefix_match.match(k))
      [match[1], v]
    end
  end.compact
  ::Hash[selected]
end

#validate(context = Attributor::DEFAULT_ROOT_CONTEXT) ⇒ Object

shamelessly copied from Attributor::Model’s #validate :(



149
150
151
152
# File 'lib/attributor/flatpack/config.rb', line 149

def validate(context = Attributor::DEFAULT_ROOT_CONTEXT)
  self.validate_attributes(context) +
    self.validate_requirements(context)
end

#validate_attributes(context) ⇒ Object



154
155
156
157
158
159
160
# File 'lib/attributor/flatpack/config.rb', line 154

def validate_attributes(context)
  self.class.attributes.each_with_object([]) do |(name, attr), errors|
    sub_context = self.generate_subcontext(context, name)
    value = self.get(name)
    errors.push(*attr.validate(value, sub_context))
  end
end

#validate_requirements(context) ⇒ Object



162
163
164
165
166
# File 'lib/attributor/flatpack/config.rb', line 162

def validate_requirements(context)
  self.class.requirements.each_with_object([]) do |req, errors|
    errors.push(req.validate(@contents, context))
  end
end