Class: PDK::Config::Namespace

Inherits:
Object
  • Object
show all
Defined in:
lib/pdk/config/namespace.rb

Direct Known Subclasses

IniFile, JSON, JSONSchemaNamespace, YAML

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = nil, file: nil, parent: nil, persistent_defaults: false, &block) ⇒ Namespace

Initialises the PDK::Config::Namespace object.

Parameters:

  • name (String) (defaults to: nil)

    the name of the namespace (defaults to nil).

  • params (Hash{Symbol => Object})

    keyword parameters for the method.

  • block (Proc)

    a block that is evaluated within the new instance.



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/pdk/config/namespace.rb', line 29

def initialize(name = nil, file: nil, parent: nil, persistent_defaults: false, &block)
  @file = PDK::Util::Filesystem.expand_path(file) unless file.nil?
  @settings = {}
  @name = name.to_s
  @parent = parent
  @persistent_defaults = persistent_defaults
  @mounts = {}
  @loaded_from_file = false
  @read_only = false

  instance_eval(&block) if block
end

Instance Attribute Details

#fileString (readonly)

Returns the path to the file associated with the contents of this namespace.

Returns:

  • (String)

    the path to the file associated with the contents of this namespace.



11
12
13
# File 'lib/pdk/config/namespace.rb', line 11

def file
  @file
end

#nameString

Determines the fully qualified name of the namespace.

If this is a child namespace, then fully qualified name for the namespace will be “<parent>.<child>”.

Returns:

  • (String)

    the fully qualifed name of the namespace.



198
199
200
# File 'lib/pdk/config/namespace.rb', line 198

def name
  child_namespace? ? [parent.name, @name].join('.') : @name
end

#parentself

Returns the parent namespace of this namespace.

Returns:

  • (self)

    the parent namespace of this namespace.



14
15
16
# File 'lib/pdk/config/namespace.rb', line 14

def parent
  @parent
end

Instance Method Details

#[](key) ⇒ Object

Note:

Unlike a Ruby Hash, this will not return ‘nil` in the event that the key does not exist (see #fetch).

Get the value of the named key.

If there is a value for that key, return it. If not, follow the logic described in #default_config_value to determine the default value to return.

Parameters:

  • key (String, Symbol)

    the name of the value to retrieve.

Returns:

  • (Object)

    the requested value.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/pdk/config/namespace.rb', line 96

def [](key)
  # Check if it's a mount first...
  return @mounts[key.to_s] unless @mounts[key.to_s].nil?
  # Check if it's a setting, otherwise nil
  return nil if settings[key.to_s].nil?
  return settings[key.to_s].value unless settings[key.to_s].value.nil?

  # Duplicate arrays and hashes so that they are isolated from changes being made
  default_value = PDK::Util.deep_duplicate(settings[key.to_s].default)
  return default_value if default_value.nil? || !@persistent_defaults

  # Persist the default value
  settings[key.to_s].value = default_value
  save_data
  default_value
end

#[]=(key, value) ⇒ nil

After the value has been set in memory, the value will then be persisted to disk.

Parameters:

  • key (String, Symbol)

    the name of the configuration value.

  • value (Object)

    the value of the configuration value.

Returns:

  • (nil)

Raises:

  • (ArgumentError)


143
144
145
146
147
148
149
150
# File 'lib/pdk/config/namespace.rb', line 143

def []=(key, value)
  # You can't set the value of a mount
  raise ArgumentError, 'Namespace mounts can not be set a value' unless @mounts[key.to_s].nil?

  set_volatile_value(key, value)
  # Persist the change
  save_data
end

#child_namespace?Boolean

Returns true if the namespace has a parent, otherwise false.

Returns:

  • (Boolean)

    true if the namespace has a parent, otherwise false.



188
189
190
# File 'lib/pdk/config/namespace.rb', line 188

def child_namespace?
  !parent.nil?
end

#fetch(key, default_value) ⇒ Object

Get the value of the named key or the provided default value if not present. Note that this does not trigger persistent defaults

This differs from #[] in an important way in that it allows you to return a default value, which is not possible using ‘[] || default` as non-existent values when accessed normally via #[] will be defaulted to a new Hash.

Parameters:

  • key (String, Symbol)

    the name of the value to fetch.

  • default_value (Object)

    the value to return if the namespace does not contain the requested value.

Returns:

  • (Object)

    the requested value.



126
127
128
129
130
131
132
133
134
# File 'lib/pdk/config/namespace.rb', line 126

def fetch(key, default_value)
  # Check if it's a mount first...
  return @mounts[key.to_s] unless @mounts[key.to_s].nil?
  # Check if it's a setting, otherwise default_value
  return default_value if settings[key.to_s].nil?

  # Check if has a value, otherwise default_value
  settings[key.to_s].value.nil? ? default_value : settings[key.to_s].value
end

#include_in_parent?Boolean

Determines if the contents of the namespace should be included in the parent namespace when persisting to disk.

If the namespace has been mounted into a parent namespace and is not associated with its own file on disk, then the values in the namespace should be included in the parent namespace when persisting to disk.

Returns:

  • (Boolean)

    true if the values should be included in the parent namespace.



211
212
213
# File 'lib/pdk/config/namespace.rb', line 211

def include_in_parent?
  child_namespace? && file.nil?
end

#mount(key, obj, &block) ⇒ self

Mount a provided [self] (or subclass) into the namespace.

Parameters:

  • key (String, Symbol)

    the name of the namespace to be mounted.

  • obj (self)

    the namespace to be mounted.

  • block (Proc)

    a block to be evaluated within the instance of the newly mounted namespace.

Returns:

  • (self)

    the mounted namespace.

Raises:

  • (ArgumentError)

    if the object to be mounted is not a self or subclass thereof.



67
68
69
70
71
72
73
74
# File 'lib/pdk/config/namespace.rb', line 67

def mount(key, obj, &block)
  raise ArgumentError, 'Only PDK::Config::Namespace objects can be mounted into a namespace' unless obj.is_a?(PDK::Config::Namespace)

  obj.parent = self
  obj.name = key.to_s
  obj.instance_eval(&block) if block
  @mounts[key.to_s] = obj
end

#namespace(name, &block) ⇒ Object

Create and mount a new child namespace.

Parameters:

  • name (String, Symbol)

    the name of the new namespace.

  • block (Proc)


80
81
82
# File 'lib/pdk/config/namespace.rb', line 80

def namespace(name, &block)
  mount(name, PDK::Config::Namespace.new, &block)
end

#read_only!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Disables the namespace, and child namespaces, from writing changes to disk. Typically this is only needed for unit testing.



218
219
220
221
222
223
# File 'lib/pdk/config/namespace.rb', line 218

def read_only!
  @read_only = true
  # pass the read_only! method as a block to the each_value method. This means that
  # for each value in the @mounts hash, the read_only! method will be called on that value.
  @mounts.each_value(&:read_only!)
end

#resolve(filter = nil) ⇒ Hash{String => Object}

Resolves all filtered settings, including child namespaces, fully namespaced and filling in default values.

Parameters:

  • filter (String) (defaults to: nil)

    Only resolve setting names which match the filter. See #be_resolved? for matching rules

Returns:

  • (Hash{String => Object})

    All resolved settings for example => ‘johndoe’



173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/pdk/config/namespace.rb', line 173

def resolve(filter = nil)
  resolved = {}
  # Resolve the settings
  settings.each_value do |setting|
    setting_name = setting.qualified_name
    if be_resolved?(setting_name, filter)
      resolved[setting_name] = setting.value.nil? ? setting.default : setting.value
    end
  end
  # Resolve the mounts
  @mounts.each_value { |mount| resolved.merge!(mount.resolve(filter)) }
  resolved
end

#setting(key, &block) ⇒ nil

Pre-configure a value in the namespace.

Allows you to specify validators and a default value for value in the namespace (see PDK::Config::Value#initialize).

Parameters:

  • key (String, Symbol)

    the name of the value.

  • block (Proc)

    a block that is evaluated within the new [self].

Returns:

  • (nil)


51
52
53
54
# File 'lib/pdk/config/namespace.rb', line 51

def setting(key, &block)
  @settings[key.to_s] ||= default_setting_class.new(key.to_s, self)
  @settings[key.to_s].instance_eval(&block) if block
end

#to_hHash{String => Object}

Convert the namespace into a Hash of values, suitable for serialising and persisting to disk.

Child namespaces that are associated with their own files are excluded from the Hash (as their values will be persisted to their own files) and nil values are removed from the Hash.

Returns:

  • (Hash{String => Object})

    the values from the namespace that should be persisted to disk.



161
162
163
164
165
166
167
# File 'lib/pdk/config/namespace.rb', line 161

def to_h
  new_hash = {}
  settings.each_pair { |k, v| new_hash[k] = v.value }
  @mounts.each_pair { |k, mount_point| new_hash[k] = mount_point.to_h if mount_point.include_in_parent? }
  new_hash.delete_if { |_k, v| v.nil? }
  new_hash
end