Class: PRC::CoreConfig

Inherits:
Object show all
Includes:
PRC::CoreConfigRubySpec::Public
Defined in:
lib/prc_core_config.rb,
lib/prc_core_config.rb,
lib/prc_core_config.rb,
lib/prc_core_config.rb

Overview

This class implement The CoreConfig system of lorj.

  • You can use it directly. See ::new.

  • you can enhance it with class heritage feature. See Class child discussion later in this class documentation.

Public functions implemented:

It implements several layer of CoreConfig object type to provide several source of data in layers priorities. Ex: RunTime => LocalConfig => AppDefault

It implements config features:

  • #[] - To get a value for a key or tree of keys

  • #[]= - To set a Config value in the highest config.

  • #del - To delete key or simply nil the value in highest config.

  • #exist? - To check the existence of a value in config levels.

  • #where? - To get the name of the level where the value was found.

  • #file - To get or set a filename to a config layer.

  • #save - To save one config data level in a yaml file.

  • #load - To load data from a yaml file to a config data layer.

  • #merge - To merge several layers data values. Values must be Hash.

When the instance is initialized, it defines 3 Config layers (BaseConfig).

If you need to define layers differently, consider to create your child class. You will be able to use SectionConfig or even any BaseConfig Child class as well.

For details about a Config layers, See BaseConfig or SectionConfig.

Child Class implementation:

This class can be enhanced with any kind of additional functionality.

You can redefine following functions exist?, [], []=, file, save, load, del, merge.

Each public functions calls pendant function, private, prefixed by _, with default options

public => private

  • #exist? => #p_exist?

  • #[] => #p_get

  • #[]= => #p_set

  • #file => #p_file

  • #save => #p_save

  • #load => #p_load

  • #del => #p_del

  • #merge => #p_get(:merge => true).

Examples:

  • Your child class can limit or re-organize config layers to query. Use :indexes or :names options to select which layer you want to query and call the core function.

    Ex: If you have 4 config levels and want to limit to 2 top ones

    def [](*keys)
      options = { keys: keys}
      options[:indexes] = [0, 1]
      p_get(options)
    end
    

    Ex: If you have 4 config levels and want to limit to 2 names.

     def [](*keys)
       options = { keys: keys}
       options[:names] = ['local', 'default_app']
       p_get(options)
    end
    
  • Your child class can force some levels options or define some extra options.

    Use :data_options to define each of them

    # Ex: If your class has 4 levels. /:name is not updatable for level 1.
    
    def [](*keys)
      options = { keys: keys }
      # The following defines data_readonly for the config level 1
      if keys[0] == :name
         options[:data_options] = [nil, {data_readonly: true}]
      end
      p_get(options)
    end
    
    # Ex: if some layer takes care of option :section, and apply to each
    # layers.
    def [](section, *keys)
      options = { keys: keys, section: section }
      p_get(options)
    end
    
    # Ex: if some layer takes care of option :section, and to apply to some
    # layers, like layer 1 and 2. (Assume with 4 layers.)
    
    def [](section, *keys)
      options = { keys: keys }
      options[:data_options] = [nil, {section: section}, {section: section}]
      p_get(options)
    end
    

Class Method Summary collapse

Instance Method Summary collapse

Methods included from PRC::CoreConfigRubySpec::Public

#[]=

Constructor Details

#initialize(config_layers = nil) ⇒ CoreConfig

initialize CoreConfig

  • Args

    • config_layers : Array config layers configuration. Each layer options have those options:

      • :config : optional. See ‘Defining Config layer instance` for details

      • :name : required. String. Name of the config layer. Warning! unique name on layers is no tested.

      • :set : boolean. True if authorized. Default is True.

      • :load : boolean. True if authorized. Default is False.

      • :save : boolean. True if authorized. Default is False.

      • :file_set : boolean. True if authorized to update a filename. Default is False.

each layers can defines some options for the layer to behave differently CoreConfig call a layer data_options to set some options, before exist?, get or [], set or []=, save and load functions. See BaseConfig::data_options for predefined options.

Core config provides some private additionnal functions for child class functions:

  • #_set_data_options(layers, options) - To set data_options on one or more config layers

  • #p_get(options) - core get function

  • #p_set(options) - core set function

  • #p_save(options) core save function

  • #p_load(options) - core load function

if config_layers is not provided, CoreConfig will instanciate a runtime like system:

config = CoreConfig.New
# is equivalent to :
config_layers = [{name: 'runtime',
                  config: PRC::BaseConfig.new, set: true}]
config = CoreConfig.New(config_layers)

Defining Config layer instance:

:config value requires it to be of type ‘BaseConfig’ By default, it uses ‘:config => PRC::BaseConfig.new` Instead, you can set:

  • directly BaseConfig. ‘:config => PRC::BaseConfig.new`

  • a child based on BaseConfig. ‘:config => MyConfig.new`

  • some predefined enhanced BaseConfig:

    • PRC::SectionConfig. See prc_section_config.rb. ‘:config => PRC::SectionConfig.new`



737
738
739
740
741
742
743
# File 'lib/prc_core_config.rb', line 737

def initialize(config_layers = nil)
  if config_layers.nil?
    config_layers = []
    config_layers << CoreConfig.define_layer
  end
  initialize_layers(config_layers)
end

Class Method Details

.define_layer(options = {}) ⇒ Object

Function to define layer options. By default, :set is true and :config is attached to a new PRC::BaseConfig instance.

Supported options:

  • :config : optional. See ‘Defining Config layer instance` for details

  • :name : required. String. Name of the config layer. Warning! unique name on layers is no tested.

  • :set : boolean. True if authorized. Default is True.

  • :load : boolean. True if authorized. Default is False.

  • :save : boolean. True if authorized. Default is False.

  • :file_set : boolean. True if authorized to update a filename. Default is False.



778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
# File 'lib/prc_core_config.rb', line 778

def self.define_layer(options = {})
  attributes = [:name, :config, :set, :load, :save, :file_set]

  layer = {}

  attributes.each do |attribute|
    if options.key?(attribute)
      layer[attribute] = options[attribute]
    else
      layer[attribute] = case attribute
                         when :name
                           'runtime'
                         when :config
                           PRC::BaseConfig.new
                         when :set
                           true
                         else
                           false
                         end
    end
  end
  layer
end

Instance Method Details

#[](*keys) ⇒ Object

Get function

  • Args

    • keys : Array of key path to found

  • Returns value found or nil.



1045
1046
1047
# File 'lib/prc_core_config.rb', line 1045

def [](*keys)
  p_get(:keys => keys)
end

#del(*keys) ⇒ Object

Del function

  • Args

    • keys : Array of key path to found and delete the last element.

  • Returns

    • The Hash updated.

ex: value = CoreConfig.New

value[:level1, :level2] = ‘value’ # => => {:level2 => ‘value’} => {:level2 => ‘value’}.del(:level1, :level2) # => => {}



1082
1083
1084
# File 'lib/prc_core_config.rb', line 1082

def del(*keys)
  p_del(:keys => keys)
end

#each(options) ⇒ Object

Function to loop in existing data in a mere view of data.

merge can return data only if at least one key value accross layers are of type Hash or Array.

  • Args

    • options : Hash of how to get the data

      • :name : layer to get data.

      • :index : layer index to get data. If neither :name or :index is set, each will use all layers

      • :data_opts : Array or Hash. Define data options per layer.



1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
# File 'lib/prc_core_config.rb', line 1243

def each(options)
  parameters = _nameindex_common_options_get(options)
  return nil if parameters.nil?

  config_layers, = parameters[0]

  return nil unless block_given?

  config_layers.each do |layer|
    layer[:config].data.each do |k, v|
      yield(k, v)
    end
  end
end

#exist?(*keys) ⇒ Boolean

exist?

  • Args

    • keys : Array of key path to found

  • Returns

    • boolean : true if the key path was found

Class child: A class child can redefine this function to increase default features.

Returns:

  • (Boolean)


1021
1022
1023
# File 'lib/prc_core_config.rb', line 1021

def exist?(*keys)
  p_exist?(:keys => keys)
end

#file(filename = nil, options = {}) ⇒ Object

Get/Set the file name.

  • Args

    • :file : file name for the layer identified.

    • options : Supported options for save

      • :index: layer index to get data.

      • :name : layer to get data. If neither :name or :index is set, nil is returned.

  • Returns

    • The file name.



1129
1130
1131
# File 'lib/prc_core_config.rb', line 1129

def file(filename = nil, options = {})
  p_file(filename, options)
end

#latest_version?(name) ⇒ Boolean

Returns:

  • (Boolean)


1196
1197
1198
1199
1200
1201
1202
1203
# File 'lib/prc_core_config.rb', line 1196

def latest_version?(name)
  return nil unless name.is_a?(String)

  index = layer_index(name)
  return nil if index.nil?

  @config_layers[index][:config].latest_version?
end

#layer_add(options) ⇒ Object

This function add a config layer at runtime.

It call an internal private function #p_layer_add which can be used by redefined in Child class.

For options and details, see #p_layer_add



751
752
753
# File 'lib/prc_core_config.rb', line 751

def layer_add(options)
  p_layer_add(options)
end

#layer_index(name) ⇒ Object

layer_index function

  • Args

  • :name : layer to identify.

  • Returns first index found or nil.



840
841
842
843
844
845
846
847
848
# File 'lib/prc_core_config.rb', line 840

def layer_index(name)
  return nil unless name.is_a?(String)
  return nil if @config_layers.nil?

  @config_layers.each_index do |index|
    return index if @config_layers[index][:name] == name
  end
  nil
end

#layer_indexes(names = nil) ⇒ Object

layer_indexes function

  • Args

    • :name : layer to identify.

    • &block: loop on layer object & index. index added if yield is true

  • Returns array of indexes found or nil.



811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
# File 'lib/prc_core_config.rb', line 811

def layer_indexes(names = nil)
  layers = []

  if block_given?
    @config_layers.each.with_index do |layer, index|
      layers << index if yield layer, index
    end
  else
    names = [names] if names.is_a?(String)
    return nil unless names.is_a?(Array)

    names.each do |name|
      index = layer_index(name)
      layers << index unless index.nil?
    end
  end

  return layers if layers.length > 0
  nil
end

#layer_remove(options) ⇒ Object

Function to remove a runtime layer.

It call an internal private function #p_layer_remove which can be used by redefined in Child class.

For options and details, see #p_layer_remove



761
762
763
# File 'lib/prc_core_config.rb', line 761

def layer_remove(options)
  p_layer_remove(options)
end

#layersObject

List all config layers defined in this instance.



1206
1207
1208
1209
1210
# File 'lib/prc_core_config.rb', line 1206

def layers
  result = []
  @config_layers.each { |layer| result << layer[:name] }
  result
end

#load(options = {}) ⇒ Object

Load from a file to the highest layer or a specific layer.

  • Args :

    • options : Supported options for load

      • :name : layer to get data.

      • :index: layer index to get data. If neither :name or :index is set, set will use the highest layer

  • Returns : -

  • Raises :

    • ++ ->



1099
1100
1101
# File 'lib/prc_core_config.rb', line 1099

def load(options = {})
  p_load(options)
end

#merge(*keys) ⇒ Object

Merge function Compare to get, merge will extract all values from each layers If those values are found and are type of Hash, merge will merge each layers values from the bottom to the top layer. ie invert of CoreConfig.layers

Note that if a layer contains a data, but not Hash, this layer will be ignored.

  • Args

    • keys : Array of key path to found

  • Returns value found merged or nil.



1064
1065
1066
# File 'lib/prc_core_config.rb', line 1064

def merge(*keys)
  p_get(:keys => keys, :merge => true)
end

#mergeable?(options) ⇒ Boolean

Function to check if merge can be used on a key. merge can return data only if at least one key value accross layers are of type Hash or Array.

  • Args

    • options : Hash of how to get the data

      • :value : Value to set

      • :keys : Array of key path to found

      • :name : layer to get data.

      • :index : layer index to get data. If neither :name or :index is set, set will use the highest layer.

      • :data_opts : Array or Hash. Define data options per layer.

      • :exclusive : true to ensure values found are exclusively Hash or Array

Returns:

  • (Boolean)


1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
# File 'lib/prc_core_config.rb', line 1147

def mergeable?(options)
  parameters = _common_options_get(options, [:keys], [:exclusive])
  return nil if parameters.nil?

  # Required options : parameters[0]
  config_layers, data_opts, keys = parameters[0]
  # Optional options : parameters[1]
  be_exclusive = parameters[1][0]

  # Merge is done in the reverse order. ie from deepest to top.
  config_layers = config_layers.reverse

  return nil if keys.length == 0 || keys[0].nil? || config_layers[0].nil?

  data_options = options.clone
  data_options.delete_if do |key, _|
    [:keys, :names, :indexes, :name, :index, :merge].include?(key)
  end

  _check_from_layers(keys, config_layers, data_opts, data_options,
                     be_exclusive)
end

#save(options = {}) ⇒ Object

Save to a file

  • Args :

    • options : Supported options for save

      • :name : layer to get data.

      • :index: layer index to get data. If neither :name or :index is set, set will use the highest layer

  • Returns : -



1114
1115
1116
# File 'lib/prc_core_config.rb', line 1114

def save(options = {})
  p_save(options)
end

#to_sObject

Display in human format.



1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
# File 'lib/prc_core_config.rb', line 1213

def to_s
  data = "Configs list ordered:\n"
  @config_layers.each do |layer|
    data += format("---- Config : %s ----\noptions: ", layer[:name])

    data += 'predefined, ' if layer[:init].is_a?(TrueClass)
    if layer[:set]
      data += 'data RW '
    else
      data += 'data RO '
    end
    data += format(", %s\n", to_s_file_opts(layer))

    data += format("%s\n", layer[:config].to_s)
  end
  data
end

#version(name) ⇒ Object

Function to get the version of a config layer name.

  • Args

    • :name : layer to get data.



1174
1175
1176
1177
1178
1179
1180
1181
# File 'lib/prc_core_config.rb', line 1174

def version(name)
  return nil unless name.is_a?(String)

  index = layer_index(name)
  return nil if index.nil?

  @config_layers[index][:config].version
end

#version_set(name, version) ⇒ Object

Function to set the version of a config layer name.

  • Args

    • :name : layer to set data version.



1187
1188
1189
1190
1191
1192
1193
1194
# File 'lib/prc_core_config.rb', line 1187

def version_set(name, version)
  return nil unless name.is_a?(String) && version.is_a?(String)

  index = layer_index(name)
  return nil if index.nil?

  @config_layers[index][:config].version = version
end

#where?(*keys) ⇒ Boolean

where?

  • Args

    • keys : Array of key path to found

  • Returns

    • boolean : true if the key path was found

Returns:

  • (Boolean)


1033
1034
1035
# File 'lib/prc_core_config.rb', line 1033

def where?(*keys)
  p_where?(:keys => keys)
end