Class: Google::Cloud::Config

Inherits:
BasicObject
Defined in:
lib/google/cloud/config.rb

Overview

Configuration mechanism for Google Cloud libraries. A Config object contains a list of predefined keys, some of which are values and others of which are subconfigurations, i.e. categories. Field access is generally validated to ensure that the field is defined, and when a a value is set, it is validated for the correct type. Warnings are printed when a validation fails.

You generally access fields and subconfigs by calling accessor methods. Methods meant for "administration" such as adding options, are named with a trailing "!" or "?" so they don't pollute the method namespace. It is also possible to access a field using the [] operator.

Note that config objects inherit from BasicObject. This means it does not define many methods you might expect to find in most Ruby objects. For example, to_s, inspect, is_a?, instance_variable_get, and so forth.

Examples:

require "google/cloud/config"

config = Google::Cloud::Config.create do |c|
  c.add_field! :opt1, 10
  c.add_field! :opt2, :one, enum: [:one, :two, :three]
  c.add_field! :opt3, "hi", match: [String, Symbol]
  c.add_field! :opt4, "hi", match: /^[a-z]+$/, allow_nil: true
  c.add_config! :sub do |c2|
    c2.add_field! :opt5, false
  end
end

config.opt1             #=> 10
config.opt1 = 20        #=> 20
config.opt1             #=> 20
config.opt1 = "hi"      #=> "hi" (but prints a warning)
config.opt1 = nil       #=> nil (but prints a warning)

config.opt2             #=> :one
config.opt2 = :two      #=> :two
config.opt2             #=> :two
config.opt2 = :four     #=> :four (but prints a warning)

config.opt3             #=> "hi"
config.opt3 = "hiho"    #=> "hiho"
config.opt3             #=> "hiho"
config.opt3 = "HI"      #=> "HI" (but prints a warning)

config.opt4             #=> "yo"
config.opt4 = :yo       #=> :yo (Strings and Symbols allowed)
config.opt4             #=> :yo
config.opt4 = 3.14      #=> 3.14 (but prints a warning)
config.opt4 = nil       #=> nil (no warning: nil allowed)

config.sub              #=> <Google::Cloud::Config>

config.sub.opt5         #=> false
config.sub.opt5 = true  #=> true  (true and false allowed)
config.sub.opt5         #=> true
config.sub.opt5 = nil   #=> nil (but prints a warning)

config.opt9 = "hi"      #=> "hi" (warning about unknown key)
config.opt9             #=> "hi" (no warning: key now known)
config.sub.opt9         #=> nil (warning about unknown key)

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Dynamic methods accessed as keys.



458
459
460
461
462
463
464
465
466
# File 'lib/google/cloud/config.rb', line 458

def method_missing name, *args
  name_str = name.to_s
  super unless name_str =~ /^[a-zA-Z]\w*=?$/
  if name_str.chomp! "="
    self[name_str] = args.first
  else
    self[name]
  end
end

Class Method Details

.config?(obj) ⇒ boolean

Determines if the given object is a config. Useful because Config does not define the is_a? method.

Returns:

  • (boolean)


104
105
106
# File 'lib/google/cloud/config.rb', line 104

def self.config? obj
  Config.send :===, obj
end

.create(show_warnings: true) {|config| ... } ⇒ Config

Constructs a Config object. If a block is given, yields self to the block, which makes it convenient to initialize the structure by making calls to add_field! and add_config!.

Parameters:

  • show_warnings (boolean)

    Whether to print warnings when a validation fails. Defaults to true.

Yields:

  • (config)

Returns:

  • (Config)

    The constructed Config object.



92
93
94
95
96
# File 'lib/google/cloud/config.rb', line 92

def self.create show_warnings: true
  config = new [], show_warnings: show_warnings
  yield config if block_given?
  config
end

Instance Method Details

#[](key) ⇒ Object

Get the option or subconfig with the given name.

Parameters:

  • key (Symbol, String)

    The option or subconfig name

Returns:

  • (Object)

    The option value or subconfig object



309
310
311
312
313
314
315
316
317
# File 'lib/google/cloud/config.rb', line 309

def [] key
  key = resolve_key! key
  unless @validators.key? key
    warn! "Key #{key.inspect} does not exist. Returning nil."
  end
  value = @values[key]
  value = value.call if Config::DeferredValue === value
  value
end

#[]=(key, value) ⇒ Object

Assign an option with the given name to the given value.

Parameters:

  • key (Symbol, String)

    The option name

  • value (Object)

    The new option value



297
298
299
300
301
# File 'lib/google/cloud/config.rb', line 297

def []= key, value
  key = resolve_key! key
  validate_value! key, @validators[key], value
  @values[key] = value
end

#add_alias!(key, to_key) ⇒ Object

Cause a key to be an alias of another key. The two keys will refer to the same field.



235
236
237
238
239
240
241
# File 'lib/google/cloud/config.rb', line 235

def add_alias! key, to_key
  key = validate_new_key! key
  @values.delete key
  @defaults.delete key
  @validators[key] = to_key.to_sym
  self
end

#add_config!(key, config = nil, &block) ⇒ Config

Add a subconfiguration field to this configuration.

You must provide a key, which becomes the method name that you use to navigate to the subconfig. Names may comprise only letters, numerals, and underscores, and must begin with a letter.

If you provide a block, the subconfig object is passed to the block, so you can easily add fields to the subconfig.

You may also pass in a config object that already exists. This will "attach" that configuration in this location.

Parameters:

  • key (String, Symbol)

    The name of the subconfig

  • config (Config) (defaults to: nil)

    A config object to attach here. If not provided, creates a new config.

Returns:

  • (Config)

    self for chaining



218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/google/cloud/config.rb', line 218

def add_config! key, config = nil, &block
  key = validate_new_key! key
  if config.nil?
    config = Config.create(&block)
  elsif block
    yield config
  end
  @values[key] = config
  @defaults[key] = config
  @validators[key] = SUBCONFIG
  self
end

#add_field!(key, initial = nil, opts = {}, &block) ⇒ Config

Add a value field to this configuration.

You must provide a key, which becomes the field name in this config. Field names may comprise only letters, numerals, and underscores, and must begin with a letter. This will create accessor methods for the new configuration key.

You may pass an initial value (which defaults to nil if not provided).

You may also specify how values are validated. Validation is defined as follows:

  • If you provide a block or a :validator option, it is used as the validator. A proposed value is passed to the proc, which should return true or false to indicate whether the value is valid.
  • If you provide a :match option, it is compared to the proposed value using the === operator. You may, for example, provide a class, a regular expression, or a range. If you pass an array, the value is accepted if any of the elements match.
  • If you provide an :enum option, it should be an Enumerable. A proposed value is valid if it is included.
  • Otherwise if you do not provide any of the above options, then a default validation strategy is inferred from the initial value:
    • If the initial is true or false, then either boolean value is considered valid. This is the same as enum: [true, false].
    • If the initial is nil, then any object is considered valid.
    • Otherwise, any object of the same class as the initial value is considered valid. This is effectively the same as match: initial.class.
  • You may also provide the :allow_nil option, which, if set to true, alters any of the above validators to allow nil values.

In many cases, you may find that the default validation behavior (interpreted from the initial value) is sufficient. If you want to accept any value, use match: Object.

Parameters:

  • key (String, Symbol)

    The name of the option

  • initial (Object) (defaults to: nil)

    Initial value (defaults to nil)

  • opts (Hash) (defaults to: {})

    Validation options

Returns:

  • (Config)

    self for chaining



188
189
190
191
192
193
194
195
196
197
# File 'lib/google/cloud/config.rb', line 188

def add_field! key, initial = nil, opts = {}, &block
  key = validate_new_key! key
  opts[:validator] = block if block
  validator = resolve_validator! initial, opts
  validate_value! key, validator, initial
  @values[key] = initial
  @defaults[key] = initial
  @validators[key] = validator
  self
end

#alias?(key) ⇒ Symbol?

Check if the given key has been explicitly added as an alias. If so, return the target, otherwise return nil.

Parameters:

  • key (Symbol)

    The key to check for.

Returns:

  • (Symbol, nil)

    The alias target, or nil if not an alias.



359
360
361
362
# File 'lib/google/cloud/config.rb', line 359

def alias? key
  target = @validators[key.to_sym]
  target.is_a?(::Symbol) ? target : nil
end

#aliases!Array<Symbol>

Return a list of alias names.

Returns:

  • (Array<Symbol>)

    a list of alias names as symbols.



387
388
389
# File 'lib/google/cloud/config.rb', line 387

def aliases!
  @validators.keys.find_all { |key| @validators[key].is_a? ::Symbol }
end

#delete!(key = nil) ⇒ Object

Remove the given key from the configuration, deleting any validation and value. If the key is omitted, delete all keys. If the key is an alias, deletes the alias but leaves the original.

Parameters:

  • key (Symbol, nil) (defaults to: nil)

    The key to delete. If omitted or nil, delete all fields and subconfigs.



278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/google/cloud/config.rb', line 278

def delete! key = nil
  if key.nil?
    @values.clear
    @defaults.clear
    @validators.clear
  else
    @values.delete key
    @defaults.delete key
    @validators.delete key
  end
  self
end

#field?(key) ⇒ boolean

Check if the given key has been explicitly added as a field name.

Parameters:

  • key (Symbol)

    The key to check for.

Returns:

  • (boolean)


338
339
340
# File 'lib/google/cloud/config.rb', line 338

def field? key
  @validators[key.to_sym].is_a? ::Proc
end

#fields!Array<Symbol>

Return a list of explicitly added field names.

Returns:

  • (Array<Symbol>)

    a list of field names as symbols.



369
370
371
# File 'lib/google/cloud/config.rb', line 369

def fields!
  @validators.keys.find_all { |key| @validators[key].is_a? ::Proc }
end

#reset!(key = nil) ⇒ Object

Restore the original default value of the given key. If the key is omitted, restore the original defaults for all keys, and all keys of subconfigs, recursively.

Parameters:

  • key (Symbol, nil) (defaults to: nil)

    The key to reset. If omitted or nil, recursively reset all fields and subconfigs.



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/google/cloud/config.rb', line 251

def reset! key = nil
  if key.nil?
    @values.each_key { |k| reset! k }
  else
    key = key.to_sym
    if @defaults.key? key
      @values[key] = @defaults[key]
      @values[key].reset! if @validators[key] == SUBCONFIG
    elsif @values.key? key
      warn! "Key #{key.inspect} has not been added, but has a value." \
            " Removing the value."
      @values.delete key
    else
      warn! "Key #{key.inspect} does not exist. Nothing to reset."
    end
  end
  self
end

#subconfig?(key) ⇒ boolean

Check if the given key has been explicitly added as a subconfig name.

Parameters:

  • key (Symbol)

    The key to check for.

Returns:

  • (boolean)


348
349
350
# File 'lib/google/cloud/config.rb', line 348

def subconfig? key
  @validators[key.to_sym] == SUBCONFIG
end

#subconfigs!Array<Symbol>

Return a list of explicitly added subconfig names.

Returns:

  • (Array<Symbol>)

    a list of subconfig names as symbols.



378
379
380
# File 'lib/google/cloud/config.rb', line 378

def subconfigs!
  @validators.keys.find_all { |key| @validators[key] == SUBCONFIG }
end

#to_h!Hash

Returns a nested hash representation of this configuration state, including subconfigs. Only explicitly added fields and subconfigs are included.

Returns:

  • (Hash)


413
414
415
416
417
418
419
420
# File 'lib/google/cloud/config.rb', line 413

def to_h!
  h = {}
  @validators.each_key do |k|
    v = @values[k]
    h[k] = Config.config?(v) ? v.to_h! : v.inspect
  end
  h
end

#to_s!String

Returns a string representation of this configuration state, including subconfigs. Only explicitly added fields and subconfigs are included.

Returns:

  • (String)


397
398
399
400
401
402
403
404
# File 'lib/google/cloud/config.rb', line 397

def to_s!
  elems = @validators.keys.map do |k|
    v = @values[k]
    vstr = Config.config?(v) ? v.to_s! : value.inspect
    " #{k}=#{vstr}"
  end
  "<Config:#{elems.join}>"
end

#value_set?(key) ⇒ boolean Also known as: option?

Check if the given key has been set in this object. Returns true if the key has been added as a normal field, subconfig, or alias, or if it has not been added explicitly but still has a value.

Parameters:

  • key (Symbol)

    The key to check for.

Returns:

  • (boolean)


327
328
329
# File 'lib/google/cloud/config.rb', line 327

def value_set? key
  @values.key? resolve_key! key
end