Class: Attributor::Flatpack::Config

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

Constant Summary collapse

DEFAULT_SEPARATOR =
'_'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data = nil) ⇒ Config

Returns a new instance of Config.



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

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

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

Class Method Details

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



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

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

.inherited(klass) ⇒ Object



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

def self.inherited(klass)
  super
  klass.instance_eval do
    @separator = Attributor::Flatpack::Config::DEFAULT_SEPARATOR
  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



123
124
125
# File 'lib/attributor/flatpack/config.rb', line 123

def [](key)
  get key
end

#[]=(key, val) ⇒ Object



127
128
129
# File 'lib/attributor/flatpack/config.rb', line 127

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

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



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/attributor/flatpack/config.rb', line 74

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



64
65
66
# File 'lib/attributor/flatpack/config.rb', line 64

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

#define_accessors(name) ⇒ Object



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

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

#define_reader(name) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/attributor/flatpack/config.rb', line 42

def define_reader(name)
  attribute = self.class.keys[name]
  context = default_context(name)

  define_singleton_method(name) do
    get(name, attribute: attribute, context: context)
  end

  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



57
58
59
60
61
62
# File 'lib/attributor/flatpack/config.rb', line 57

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

#fetch(key) ⇒ Object

search @raw for key



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/attributor/flatpack/config.rb', line 100

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_value

  yield if block_given?
end

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

Raises:



68
69
70
71
72
# File 'lib/attributor/flatpack/config.rb', line 68

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



131
132
133
134
135
136
137
138
# File 'lib/attributor/flatpack/config.rb', line 131

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



160
161
162
163
164
165
166
167
168
169
170
# File 'lib/attributor/flatpack/config.rb', line 160

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



89
90
91
92
93
94
95
96
97
# File 'lib/attributor/flatpack/config.rb', line 89

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



112
113
114
115
116
117
118
119
120
121
# File 'lib/attributor/flatpack/config.rb', line 112

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 :(



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

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

#validate_attributes(context) ⇒ Object



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

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



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

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