Class: BBK::Utils::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/bbk/utils/config.rb,
sig/bbk/config.rbs

Defined Under Namespace

Modules: _CallableCaster, _ClassCaster Classes: BooleanCaster, KeyError

Constant Summary collapse

PREFIX_SEP =
'_'
FILTERED_VALUE =
'[FILTERED]'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name: nil, prefix: nil, parent: nil) ⇒ Config

Returns a new instance of Config.

Parameters:

  • name: (String, nil) (defaults to: nil)
  • prefix: (String, nil) (defaults to: nil)
  • parent: (BBK::Utils::Config, nil) (defaults to: nil)


54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/bbk/utils/config.rb', line 54

def initialize(name: nil, prefix: nil, parent: nil)
  @name = name
  @store = {}
  @parent = parent
  @subconfigs = []
  @prefix = normalize_key(prefix)
  @prefixes = if parent.nil?
    [@prefix]
  else
    parent.prefixes.dup + [@prefix]
  end.compact
  @env_prefix = normalize_key(@prefixes.join(PREFIX_SEP))
end

Instance Attribute Details

#env_prefixObject (readonly)

Returns the value of attribute env_prefix.



11
12
13
# File 'lib/bbk/utils/config.rb', line 11

def env_prefix
  @env_prefix
end

#nameString?

Returns the value of attribute name.

Returns:

  • (String, nil)


10
11
12
# File 'lib/bbk/utils/config.rb', line 10

def name
  @name
end

#parentObject (readonly)

Returns the value of attribute parent.



11
12
13
# File 'lib/bbk/utils/config.rb', line 11

def parent
  @parent
end

#prefixObject (readonly)

Returns the value of attribute prefix.



11
12
13
# File 'lib/bbk/utils/config.rb', line 11

def prefix
  @prefix
end

#storeObject

Returns the value of attribute store.

Returns:

  • (Object)


10
11
12
# File 'lib/bbk/utils/config.rb', line 10

def store
  @store
end

Class Method Details

.instance(prefix: nil) ⇒ instance

Returns:



38
39
40
# File 'lib/bbk/utils/config.rb', line 38

def self.instance(prefix: nil)
  @instance ||= new(prefix: prefix)
end

.parse_bool_value(value) ⇒ Object



42
43
44
# File 'lib/bbk/utils/config.rb', line 42

def self.parse_bool_value(value)
  BooleanCaster.cast(value)
end

Instance Method Details

#[](key) ⇒ Object

Parameters:

  • key (String)

Returns:

  • (Object)


142
143
144
# File 'lib/bbk/utils/config.rb', line 142

def [](key)
  self.get(key, search_up: true, search_down: true)[:value]
end

#[]=(key, value) ⇒ void

This method returns an undefined value.

Parameters:

  • key (String)
  • value (Object)


146
147
148
# File 'lib/bbk/utils/config.rb', line 146

def []=(key, value)
  @store[normalize_key(key)][:value] = value
end

#as_json(*_args) ⇒ Hash[String, untyped]

def to_s: () -> String

Parameters:

  • (Object)

Returns:

  • (Hash[String, untyped])


38
39
40
41
42
43
44
45
46
# File 'sig/bbk/config.rbs', line 38

def as_json(*_args)
  values = store_with_subconfigs.values.sort_by do |item|
    [item[:file].present? ? 0 : 1, item[:required] ? 0 : 1]
  end.reduce({}) do |ret, item|
    ret.merge(item[:env] => item)
  end

  @name ? { @name => values } : values
end

#content(key) ⇒ Object

Parameters:

  • key (String)

Returns:

  • (Object)


150
151
152
153
154
155
156
157
# File 'lib/bbk/utils/config.rb', line 150

def content(key)
  item = @store[normalize_key(key)]
  if (file = item[:file])
    File.read(file)
  else
    item[:value]
  end
end

#fetch(key, default = nil) ⇒ Object

Parameters:

  • key (String)
  • default (Object) (defaults to: nil)

Returns:

  • (Object)


159
160
161
162
163
164
165
166
167
# File 'lib/bbk/utils/config.rb', line 159

def fetch(key, default = nil)
  if (rec = self.get(key, search_up: true, search_down: true)) && rec.key?(:value)
    rec[:value]
  else
    default
  end
rescue KeyError
  default
end

#map(env, file, required: true, desc: nil, bool: false, key: nil, rewrite: true, category: nil, warning: nil) ⇒ void

This method returns an undefined value.

Parameters:

  • env (envSource)
  • file (String)
  • required: (Boolean) (defaults to: true)
  • desc: (String) (defaults to: nil)
  • bool: (Boolean) (defaults to: false)
  • key: (String) (defaults to: nil)
  • rewrite: (Boolean) (defaults to: true)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/bbk/utils/config.rb', line 68

def map(env, file, required: true, desc: nil, bool: false, key: nil, rewrite: true, category: nil, warning: nil)
  conf_key = full_prefixed_key(env)
  return if @store.key?(conf_key) && !rewrite

  @store[conf_key] = {
    env:      full_prefixed_key(key || env),
    file:     file,
    required: required,
    desc:     desc,
    bool:     bool,
    type:     nil,
    category: category,
    warning:  warning
  }
end

#normalize_key(key) ⇒ String?

Parameters:

  • key (String, nil)

Returns:

  • (String, nil)


245
246
247
248
249
# File 'lib/bbk/utils/config.rb', line 245

def normalize_key(key)
  return nil if key.nil?

  key.to_s.upcase.gsub('-', '_')
end

#optional(env, default: nil, desc: nil, bool: false, type: nil, key: nil, rewrite: true, secure: false, category: nil, warning: nil) ⇒ void

This method returns an undefined value.

Parameters:

  • env (envSource)
  • default: (Object) (defaults to: nil)
  • desc: (String) (defaults to: nil)
  • bool: (Boolean) (defaults to: false)
  • type: (typeCaster) (defaults to: nil)
  • key: (String) (defaults to: nil)
  • rewrite: (Boolean) (defaults to: true)

Raises:

  • (ArgumentError)


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/bbk/utils/config.rb', line 104

def optional(env, default: nil, desc: nil, bool: false, type: nil, key: nil, rewrite: true, secure: false, category: nil, warning: nil)
  raise ArgumentError.new('Specified type and bool') if bool && type.present?

  type = BBK::Utils::Config::BooleanCaster.singleton_method(:cast) if bool
  conf_key = full_prefixed_key(env)
  return if @store.key?(conf_key) && !rewrite

  @store[conf_key] = {
    env:      full_prefixed_key(key || env),
    file:     nil,
    required: false,
    default:  default,
    desc:     desc,
    bool:     true,
    type:     type,
    secure:   secure,
    category: category,
    warning:  warning
  }
end

Parameters:

  • item (configItem)
  • padding (String)

Returns:

  • (String)


312
313
314
315
316
317
318
319
320
321
# File 'lib/bbk/utils/config.rb', line 312

def print_file_item(item, padding)
  line = "#{padding}File #{wrap_required(item)}"
  line = if item[:desc].present?
    "#{line.ljust(50)} #{item[:desc]}"
  else
    line
  end

  "#{line}\n#{padding * 2}-> #{item[:file].inspect}"
end

Parameters:

  • item (configItem)
  • padding (String)

Returns:

  • (String)


323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/bbk/utils/config.rb', line 323

def print_item(item, padding)
  line = padding + wrap_required(item)
  if item[:default].present?
    def_value = if item[:secure]
      FILTERED_VALUE
    else
      item[:default]
    end
    line += " (=#{def_value})"
  end

  line = if item[:desc].present?
    "#{line.ljust(50)} #{item[:desc]}"
  else
    line
  end
  value = if item[:secure]
    FILTERED_VALUE
  else
    item[:value].inspect
  end
  "#{line}\n#{padding * 2}-> #{value}"
end

#process(source, item) ⇒ void

This method returns an undefined value.

Parameters:

  • source (envSource)
  • item (configItem)


268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/bbk/utils/config.rb', line 268

def process(source, item)
  content = source.fetch(item[:env], item[:default])

  # Если данные есть, либо указан тип (нужно для того чтобы переменная была нужного типа)
  if content.present? || item[:type].present?
    if (file = item[:file])
      dirname = File.dirname(file)
      FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
      File.write(file, content)
      item[:value] = file
    else
      item[:value] = if (type = item[:type])
        if type.respond_to? :call
          type.call(content)
        else
          type.new(content)
        end
      else
        content
      end
    end
  elsif item[:required]
    required!(item)
  else
    item[:value] = if (file = item[:file]).present? && File.exist?(file)
      file
    else
      content
    end
  end
rescue StandardError => e
  msg = "Failed processing #{item[:env]} parameter. #{e.inspect}"
  if $logger
    $logger.error msg
  else
    puts msg
  end
  raise
end

#require(env, desc: nil, bool: false, type: nil, key: nil, rewrite: true, secure: false, category: nil, warning: nil) ⇒ void

This method returns an undefined value.

Parameters:

  • env (envSource)
  • desc: (String, nil) (defaults to: nil)
  • bool: (Boolean) (defaults to: false)
  • type: (typeCaster) (defaults to: nil)
  • key: (String, nil) (defaults to: nil)
  • rewrite: (Boolean) (defaults to: true)

Raises:

  • (ArgumentError)


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

def require(env, desc: nil, bool: false, type: nil, key: nil, rewrite: true, secure: false, category: nil, warning: nil)
  raise ArgumentError.new('Specified type and bool') if bool && type.present?

  type = BBK::Config::BooleanCaster.singleton_method(:cast) if bool
  conf_key = full_prefixed_key(env)
  return if @store.key?(conf_key) && !rewrite

  @store[conf_key] = {
    env:      full_prefixed_key(key || env),
    file:     nil,
    required: true,
    desc:     desc,
    bool:     bool,
    type:     type,
    secure:   secure,
    category: category,
    warning:  warning
  }
end

#required!(item) ⇒ void

This method returns an undefined value.

Parameters:

  • item (configItem)


308
309
310
# File 'lib/bbk/utils/config.rb', line 308

def required!(item)
  raise "ENV [#{item[:env]}] is required!"
end

#root?Boolean

Returns:

  • (Boolean)


205
206
207
# File 'lib/bbk/utils/config.rb', line 205

def root?
  @parent.nil?
end

#run!(source = ENV) ⇒ void

This method returns an undefined value.

Parameters:

  • source (envSource) (defaults to: ENV)


125
126
127
128
129
130
131
# File 'lib/bbk/utils/config.rb', line 125

def run!(source = ENV)
  @store.each_value do |item|
    process(source, item)
  end
  @subconfigs.each {|sub| sub.run!(source) }
  nil
end

#subconfig(prefix:, name: nil) {|sub| ... } ⇒ Object

Yields:

  • (sub)

Raises:

  • (ArgumentError)


133
134
135
136
137
138
139
140
# File 'lib/bbk/utils/config.rb', line 133

def subconfig(prefix:, name: nil)
  raise ArgumentError.new("Subconfig with prefix #{prefix} already exists") if @subconfigs.any? {|sub| sub.prefix == prefix.to_s }

  sub = self.class.new(name: name, prefix: prefix, parent: self)
  @subconfigs << sub
  yield sub if block_given?
  sub
end

#to_json(*_args) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


197
198
199
# File 'lib/bbk/utils/config.rb', line 197

def to_json(*_args)
  JSON.pretty_generate(as_json)
end

#to_sObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/bbk/utils/config.rb', line 169

def to_s
  result = StringIO.new
  result.puts "Environment variables#{@name ? " for #{@name}" : ''}:"
  padding = ' ' * 3
  sorted = store_with_subconfigs.values.sort_by do |item|
    [item[:file].present? ? 0 : 1, item[:required] ? 0 : 1]
  end

  sorted.each do |item|
    if item[:file]
      result.puts print_file_item(item, padding)
    else
      result.puts print_item(item, padding)
    end
  end
  result.string
end

#to_yaml(*_args) ⇒ String

Parameters:

  • (Object)

Returns:

  • (String)


201
202
203
# File 'lib/bbk/utils/config.rb', line 201

def to_yaml(*_args)
  JSON.parse(to_json).to_yaml
end

#wrap_required(item) ⇒ String

Parameters:

  • item (configItem)

Returns:

  • (String)


347
348
349
350
351
352
353
# File 'lib/bbk/utils/config.rb', line 347

def wrap_required(item)
  if item[:required]
    "<#{item[:env]}>"
  else
    "[#{item[:env]}]"
  end
end