class Nucleon::Util::Data

Data utilities

The Nucleon::Util::Data class defines various tools for working with data in the Nucleon system.

It implements:

  1. Type checkers

  2. Basic data translators

  3. Data transformations

  4. Other utilities

Public Class Methods

array(data, default = [], split_string = false) click to toggle source

Ensure a data object is an array.

It converts:

  1. Symbols to arrays

  2. Strings to arrays

  3. Splits strings on commas (if split_string requested)

  4. If no array found, returns default

TODO: Parameter for string separator split

  • Parameters

    • ANY

      data Ruby data to ensure array

    • Array

      default Default value if no array is found

    • Boolean

      split_string Whether to split strings on comma

  • Returns

    • Array

      Returns an array

  • Errors

See also:

    # File lib/core/util/data.rb
438 def self.array(data, default = [], split_string = false)
439   result = default
440   if data
441     case data
442     when Array
443       result = data
444     when String
445       result = [ ( split_string ? data.split(/\s*,\s*/) : data ) ]
446     else
447       result = [ data ]
448     end
449   end
450   return result
451 end
clean(data, remove_empty = true) click to toggle source

Clean nil or empty values out of a hash object.

  • Parameters

    • Hash

      data Ruby data to clean properties

    • Boolean

      remove_empty Whether or not to remove empty values or just nil

  • Returns

    • Hash

      Returns hash with all nil or empty values scrubbed (depending on remove_empty)

  • Errors

See also:

    # File lib/core/util/data.rb
601 def self.clean(data, remove_empty = true)
602   data.keys.each do |key|
603     obj = data[key]
604     data.delete(key) if obj.nil? || ( remove_empty && obj.is_a?(Hash) && obj.empty? )
605   end
606   data
607 end
clone(data) click to toggle source

Recursively clone an array or tree based hash object.

  • Parameters

    • Hash, Array

      data Ruby data to recursively clone

  • Returns

    • Hash

      Returns completely new nested hash if hash data given

    • Array

      Returns completely new array if array data given

  • Errors

    # File lib/core/util/data.rb
649 def self.clone(data)
650   if data.is_a?(Array)
651     new_data = []
652     data.each do |item|
653       new_data << clone(item)
654     end
655   elsif data.is_a?(Hash)
656     new_data = {}
657     data.each do |key, value|
658       new_data[key] = clone(value)
659     end
660   else
661     new_data = data
662   end
663   new_data
664 end
deep_clean(data, remove_empty = true) click to toggle source

Recursively clean nil or empty values out of a hash object.

  • Parameters

    • Hash

      data Ruby data to clean properties

    • Boolean

      remove_empty Whether or not to remove empty values or just nil

  • Returns

    • Hash

      Returns hash with all nil or empty values scrubbed (depending on remove_empty)

  • Errors

See also:

    # File lib/core/util/data.rb
623 def self.deep_clean(data, remove_empty = true)
624   data.keys.each do |key|
625     obj = data[key]
626 
627     if obj.nil? || ( remove_empty && obj.is_a?(Hash) && obj.empty? )
628       data.delete(key)
629 
630     elsif data[key].is_a?(Hash)
631       deep_clean(data[key], remove_empty)
632     end
633   end
634   data
635 end
empty?(value) click to toggle source

Check if given value is empty.

It currently checks for: (our definition of empty)

This method was created to provide an easy way for us to load and work with configurations from text formats, such as JSON.

  • Parameters

    • ANY

      value Value to check if empty

  • Returns

    • Boolean

      Returns true if value is empty, false otherwise

  • Errors

    # File lib/core/util/data.rb
120 def self.empty?(value)
121   if undef?(value) || false?(value) || (value.respond_to?('empty?') && value.empty?)
122     return true
123   end
124   return false
125 end
ensure(test, success_value = nil, failure_value = nil) click to toggle source

Ensure a value is set one way or another depending on a test condition.

  • Parameters

    • Boolean

      test Test for success / failure

    • ANY

      success_value Value returned if test is not empty

    • ANY

      failure_value Value returned if test is empty

  • Returns

    • ANY

      Success or failure values depending on the outcome of test

  • Errors

See also:

    # File lib/core/util/data.rb
925 def self.ensure(test, success_value = nil, failure_value = nil)
926   success_value = (success_value ? success_value : test)
927   failure_value = (failure_value ? failure_value : nil)
928 
929   if empty?(test)
930     value = failure_value
931   else
932     value = success_value
933   end
934   return value
935 end
ensure_value(value, failure_value = nil) click to toggle source

Return value if not empty or else return failure value.

  • Parameters

    • ANY

      value Test for success / failure

    • ANY

      failure_value Value returned if value is empty

  • Returns

    • ANY

      Value or failure value depending on the emptiness of value

  • Errors

See:

    # File lib/core/util/data.rb
951 def self.ensure_value(value, failure_value = nil)
952   return self.ensure(value, nil, failure_value)
953 end
exists?(data, keys, check_empty = false) click to toggle source

Check if given keys exist in data hash.

This method allows for the easy checking of nested keys. It takes care of traversing the data structure and checking for empty recursively.

  • Parameters

    • Hash<String, Symbol|…|ANY>

      data Data object to check

    • Array<String, Symbol>

      keys Hash key path (nested keys)

    • Boolean

      check_empty Whether to check element for emptiness

  • Returns

    • Boolean

      Returns true if keys exist and not empty, false otherwise if check_empty

    • Boolean

      Returns true if keys exist, false otherwise

  • Errors

See:

    # File lib/core/util/data.rb
146 def self.exists?(data, keys, check_empty = false)
147   if keys.is_a?(String) || keys.is_a?(Symbol)
148     keys = [ keys ]
149   end
150   key = keys.shift.to_sym
151 
152   if data.has_key?(key)
153     value = data[key]
154 
155     if keys.empty?
156       return false if check_empty && empty?(value)
157       return true
158     else
159       return exists?(data[key], keys)
160     end
161   end
162   return false
163 end
false?(value) click to toggle source

Check if given value is false.

It currently checks for: (our definition of false)

  • false

  • Symbols: :false

  • Strings: “false”, “FALSE”, “False

This method was created to provide an easy way for us to load and work with configurations from text formats, such as JSON.

  • Parameters

    • ANY

      value Value to check if false

  • Returns

    • Boolean

      Returns true if value is false, false otherwise

  • Errors

    # File lib/core/util/data.rb
 93 def self.false?(value)
 94   if value == false ||
 95     (value.is_a?(Symbol) && value == :false) ||
 96     (value.is_a?(String) && value.match(/^\s*(false|FALSE|False)\s*$/))
 97     return true
 98   end
 99   return false
100 end
filter(data, method = false) click to toggle source

Run a defined filter on a data object.

This method ensures that a given data object meets some criteria or else an empty value for that type is returned that matches the criteria.

Currently implemented filters:

  1. ::array Ensure result is an array (non arrays are converted)

  2. ::hash Ensure result is a hash (non hashes are converted)

  3. ::string Ensure result is a string (non strings are converted)

  4. ::symbol Ensure result is a symbol (non symbols are converted)

  5. ::test Ensure result is not empty (runs a boolean ::empty? check)

More filters can be added by adding methods to the Nucleon::Util::Data class.

For example:

module Nucleon::Util::Data
  def my_filter(data, default = '')
    # Return data modified or default
  end
end

my_data = Nucleon::Util::Data.filter(my_data, :my_filter)
  • Parameters

    • ANY

      data Ruby data object to run through filter

    • false, String

      method Filter method to execute or false for none

  • Returns

    • ANY

      Returns filtered data object

  • Errors

    # File lib/core/util/data.rb
404 def self.filter(data, method = false)
405   if method && respond_to?(method.to_sym)
406     return send(method.to_sym, data)
407   end
408   return data
409 end
hash(data, default = {}) click to toggle source

Ensure a data object is a hash.

If data is given and it is not a hash, an empty hash is returned in it’s place.

  • Parameters

    • ANY

      data Ruby data to ensure hash

    • Hash

      default Default value if no data is given (nil)

  • Returns

    • Hash

      Returns a hash

  • Errors

See also:

    # File lib/core/util/data.rb
474 def self.hash(data, default = {})
475   result = default
476   if data
477     case data
478     when Hash
479       result = data
480     else
481       result = {}
482     end
483   end
484   return result
485 end
interpolate(value, scope, options = {}) click to toggle source

Interpolate values into data objects based on patterns.

This method interpolates values into either a single string or a hash of strings that are recursively processed.

This method requires our Hash#search method defined in the mod folder.

  • Parameters

    • String, Hash

      value Value to interpolate properties into

    • Hash

      scope Property values for text replacements

    • Hash

      options Method options

      • String

        :pattern Regexp pattern to match intepolated properties against

      • Integer

        :var_group Regexp group match for property name

      • String

        :flags Optional Regexp flags

  • Returns

    • String, Hash

      Returns interpolated string or hash of strings

  • Errors

See also:

    # File lib/core/util/data.rb
762 def self.interpolate(value, scope, options = {})
763 
764   pattern = ( options.has_key?(:pattern) ? options[:pattern] : '\$(\{)?([a-zA-Z0-9\_\-]+)(\})?' )
765   group   = ( options.has_key?(:var_group) ? options[:var_group] : 2 )
766   flags   = ( options.has_key?(:flags) ? options[:flags] : '' )
767 
768   if scope.is_a?(Hash)
769     regexp = Regexp.new(pattern, flags.split(''))
770 
771     replace = lambda do |item|
772       matches = item.match(regexp)
773       result  = nil
774 
775       unless matches.nil?
776         replacement = scope.search(matches[group], options)
777         result      = item.gsub(matches[0], replacement) unless replacement.nil?
778       end
779       return result
780     end
781 
782     case value
783     when String
784       while (temp = replace.call(value))
785         value = temp
786       end
787 
788     when Hash
789       value.each do |key, data|
790         value[key] = interpolate(data, scope, options)
791       end
792     end
793   end
794   return value
795 end
merge(data, force = true, basic = true) click to toggle source

Merge data objects together.

This method relies on the merging capabilities of the deep_merge gem. It switches between core Ruby shallow merge and deep_merge merges based on the basic boolean.

Elements at the end of the array override values for data at the beginning.

  • Parameters

    • Array<nil, String, Symbol, Array, Hash>

      data Ruby data objects to merge

    • Boolean

      force Whether or not to force override of values where types don’t match

    • Boolean

      basic Whether or not to perform a basic merge or deep (recursive) merge

  • Returns

    • nil, String, Symbol, Array, Hash

      Returns merged data object

  • Errors

See also:

    # File lib/core/util/data.rb
687 def self.merge(data, force = true, basic = true)
688   value = data
689 
690   # Special case because this method is called from within Config.new so we
691   # can not use Config.ensure, as that would cause an infinite loop.
692   if force.is_a?(Nucleon::Config)
693     basic = force.get(:basic, true)
694     force = force.get(:force, true)
695   end
696 
697   if data.is_a?(Array)
698     value = undef?(data[0]) ? nil : data.shift.clone
699 
700     data.each do |item|
701       item = undef?(item) ? nil : item.clone
702 
703       case value
704       when Hash
705         if basic
706           if item.is_a?(Hash)
707             value = value.merge(item)
708           elsif force
709             value = item
710           end
711         else
712           begin
713             require 'deep_merge'
714             value = force ? value.deep_merge!(item) : value.deep_merge(item)
715 
716           rescue LoadError
717             if item.is_a?(Hash) # Non recursive top level by default.
718               value = value.merge(item)
719             elsif force
720               value = item
721             end
722           end
723         end
724       when Array
725         if item.is_a?(Array)
726           value = value.concat(item).uniq
727         elsif force
728           value = item
729         end
730 
731       else
732         value = item if force || item.is_a?(String) || item.is_a?(Symbol)
733       end
734     end
735   end
736   return value
737 end
parse_json(json_text) click to toggle source

Parse a JSON string into a Ruby data object.

This method uses the MultiJson gem to carry out the heavy lifting. We just sit back and enjoy the ride.

  • Parameters

    • String

      json_text JSON text string to parse into Ruby data

  • Returns

    • nil, true, false, String, Array, Hash<String|…|ANY>

      Returns parsed data object

  • Errors

See also:

    # File lib/core/util/data.rb
262 def self.parse_json(json_text)
263   return MultiJson.load(json_text)
264 end
parse_yaml(yaml_text) click to toggle source

Parse a YAML string into a Ruby data object.

This method uses the Ruby YAML module to carry out the heavy lifting. We just sit back and enjoy the ride.

  • Parameters

    • String

      yaml_text YAML text string to parse into Ruby data

  • Returns

    • nil, true, false, String, Array, Hash<String|…|ANY>

      Returns parsed data object

  • Errors

See also:

    # File lib/core/util/data.rb
302 def self.parse_yaml(yaml_text)
303   return YAML.load(yaml_text)
304 end
prefix(prefix, data, pad = '_') click to toggle source

Prefix every element in data with prefix separated by pad.

This method basically just does bulk prefixing. This has come in useful in quite a few applications, particularly with dealing with configurations.

This method can recursively set prefixes for hash keys as well.

  • Parameters

    • String

      prefix Prefix string to prepend to data elements

    • String, Symbol, Array, Hash

      data Data elements to prefix

    • String

      pad Whether or not to symbolize data keys before selection

  • Returns

    • String, Symbol, Array, Hash

      Returns prefixed data object

  • Errors

See also:

    # File lib/core/util/data.rb
883 def self.prefix(prefix, data, pad = '_')
884   result = nil
885 
886   unless prefix.is_a?(Symbol) || ( prefix.is_a?(String) && ! empty?(prefix) )
887     prefix = ''
888   end
889   prefix = prefix.to_s
890 
891   case data
892   when String, Symbol
893     result = ( prefix.empty? ? data.to_s : prefix + pad + data.to_s )
894 
895   when Array
896     result = []
897     data.each do |value|
898       result << prefix(prefix, value, pad)
899     end
900 
901   when Hash
902     result = {}
903     data.each do |key, value|
904       result[prefix(prefix, key, pad)] = value
905     end
906   end
907   return result
908 end
rm_keys(data, keys, symbolize = false) click to toggle source

Remove keys from a given hash.

This method first symbolizes all keys of the hash and then deletes any matching elements if the symbolize option is given.

  • Parameters

    • Hash

      data Ruby hash to remove keys from

    • String, Symbol, Array

      keys Keys to remove from

    • Boolean

      symbolize Whether or not to symbolize data keys before removal

  • Returns

    • Hash

      Returns cleaned data object

  • Errors

See also:

    # File lib/core/util/data.rb
816 def self.rm_keys(data, keys, symbolize = false)
817   keys = [ keys ] unless keys.is_a?(Array)
818   data = hash(data)
819   data = symbol_map(data) if symbolize
820 
821   keys.each do |key|
822     key = key.to_sym if symbolize
823     data.delete(key)
824   end
825   data
826 end
string(data, default = '') click to toggle source

Ensure a data object is a string.

If data is given and it is not a string, the data.to_s method is called to get the rendered string.

  • Parameters

    • ANY

      data Ruby data to ensure string

    • String

      default Default value if no data is given (nil)

  • Returns

    • String

      Returns a string

  • Errors

See also:

    # File lib/core/util/data.rb
508 def self.string(data, default = '')
509   result = default
510   if data
511     case data
512     when String
513       result = data
514     else
515       result = data.to_s
516     end
517   end
518   return result
519 end
string_map(data) click to toggle source

Return hash as a string map.

This method converts all hash keys to strings. Nested hashes are recursively translated as well.

This comes in really handy when performing operations across hashes in Ruby because of the distinction between symbols and strings.

  • Parameters

    • Hash<String, Symbol|…|ANY>

      data Hash data to stringify keys

  • Returns

    • Hash<String|…|ANY>

      Returns data structure grouped by string keys

  • Errors

See also:

    # File lib/core/util/data.rb
226 def self.string_map(data)
227   results = {}
228   return data unless data
229 
230   case data
231   when Hash
232     data.each do |key, value|
233       results[key.to_s] = string_map(value)
234     end
235   when Array
236     results = []
237     data.each do |value|
238       results << string_map(value)
239     end
240   else
241     results = data
242   end
243   return results
244 end
subset(data, keys, symbolize = false) click to toggle source

Select specific keys from a given hash.

This method first symbolizes all keys of the hash and then deletes any matching elements if the symbolize option is given.

  • Parameters

    • Hash

      data Ruby hash to select keys from

    • String, Symbol, Array

      keys Keys to select

    • Boolean

      symbolize Whether or not to symbolize data keys before selection

  • Returns

    • Hash

      Returns data object with selected keys

  • Errors

See also:

    # File lib/core/util/data.rb
847 def self.subset(data, keys, symbolize = false)
848   keys     = [ keys ] unless keys.is_a?(Array)
849   data     = hash(data)
850   data     = symbol_map(data) if symbolize
851   new_data = {}
852 
853   keys.each do |key|
854     key           = key.to_sym if symbolize
855     new_data[key] = data[key] if data.has_key?(key)
856   end
857   new_data
858 end
symbol(data, default = :undefined) click to toggle source

Ensure a data object is a symbol.

If data is given and it is not a symbol, the data.to_sym method is called to get the generated symbol. If data is not a string or symbol, it’s class name is symbolized.

  • Parameters

    • ANY

      data Ruby data to ensure symbol

    • Symbol

      default Default value if no data is given (:undefined)

  • Returns

    • Symbol

      Returns a symbol

  • Errors

See also:

    # File lib/core/util/data.rb
543 def self.symbol(data, default = :undefined)
544   result = default
545   if data
546     case data
547     when TrueClass, FalseClass
548       result = data ? :true : :false
549     when Symbol
550       result = data
551     when String
552       result = data.to_sym
553     else
554       result = data.class.to_sym
555     end
556   end
557   return result
558 end
symbol_map(data) click to toggle source

Return hash as a symbol map.

This method converts all hash keys to symbols. Nested hashes are recursively translated as well.

This comes in really handy when performing operations across hashes in Ruby because of the distinction between symbols and strings.

  • Parameters

    • Hash<String, Symbol|…|ANY>

      data Hash data to symbolize keys

  • Returns

    • Hash<Symbol|…|ANY>

      Returns data structure symbolized

  • Errors

See also:

    # File lib/core/util/data.rb
187 def self.symbol_map(data)
188   results = {}
189   return data unless data
190 
191   case data
192   when Hash
193     data.each do |key, value|
194       results[key.to_sym] = symbol_map(value)
195     end
196   when Array
197     results = []
198     data.each do |value|
199       results << symbol_map(value)
200     end
201   else
202     results = data
203   end
204   return results
205 end
test(data) click to toggle source

Test a data object for emptiness and return boolean result.

Uses the ::empty? method to check for emptiness.

  • Parameters

    • ANY

      data Ruby data to test for emptiness

  • Returns

    • Boolean

      Returns true if data not empty, false otherwise

  • Errors

See also:

    # File lib/core/util/data.rb
579 def self.test(data)
580   return false if Util::Data.empty?(data)
581   return true
582 end
to_json(data, pretty = true) click to toggle source

Dump a Ruby object to a JSON string.

This method uses the MultiJson gem to carry out the heavy lifting. We just sit back and enjoy the ride.

  • Parameters

    • ANY

      data Ruby data to render JSON string

  • Returns

    • String

      Returns JSON rendered data object

  • Errors

See also:

    # File lib/core/util/data.rb
282 def self.to_json(data, pretty = true)
283   return MultiJson.dump(data, :pretty => pretty)
284 end
to_yaml(data) click to toggle source

Dump a Ruby object to a YAML string.

This method uses the Ruby YAML module to carry out the heavy lifting. We just sit back and enjoy the ride.

  • Parameters

    • ANY

      data Ruby data to render YAML string

  • Returns

    • String

      Returns YAML rendered data object

  • Errors

See also:

    # File lib/core/util/data.rb
322 def self.to_yaml(data)
323   return YAML.dump(data)
324 end
true?(value) click to toggle source

Check if given value is true.

It currently checks for: (our definition of true)

  • true

  • Symbols: :true

  • Strings: “true”, “TRUE”, “True

This method was created to provide an easy way for us to load and work with configurations from text formats, such as JSON.

  • Parameters

    • ANY

      value Value to check if true

  • Returns

    • Boolean

      Returns true if value is true, false otherwise

  • Errors

   # File lib/core/util/data.rb
66 def self.true?(value)
67   if value == true ||
68     (value.is_a?(Symbol) && value == :true) ||
69     (value.is_a?(String) && value.match(/^\s*(true|TRUE|True)\s*$/))
70     return true
71   end
72   return false
73 end
undef?(value) click to toggle source

Check if given value is undefined.

It currently checks for: (our definition of undefined)

  • nil

  • Symbols: :undef, :undefined

  • Strings: “undef”, “UNDEF”, “Undef”, “nil”, “NIL”, “Nil

This method was created to provide an easy way for us to load and work with configurations from text formats, such as JSON.

  • Parameters

    • ANY

      value Value to check if undefined

  • Returns

    • Boolean

      Returns true if value is undefined, false otherwise

  • Errors

   # File lib/core/util/data.rb
39 def self.undef?(value)
40   if value.nil? ||
41     (value.is_a?(Symbol) && value == :undef || value == :undefined) ||
42     (value.is_a?(String) && value.match(/^\s*(undef|UNDEF|Undef|nil|NIL|Nil)\s*$/))
43     return true
44   end
45   return false
46 end
value(value, undefined_value = nil) click to toggle source

Translate a value to internally standardized form.

It currently translates:

This method was created to provide an easy way for us to load and work with configurations from text formats, such as JSON.

  • Parameters

    • ANY

      value Value to internalize

    • ANY

      undefined_value Value that represents undefined (nil)

  • Returns

    • ANY

      Returns internalized value object

  • Errors

    # File lib/core/util/data.rb
347 def self.value(value, undefined_value = nil)
348   case value
349   when String
350     if undef?(value)
351       value = undefined_value
352     elsif true?(value)
353       value = true
354     elsif false?(value)
355       value = false
356     end
357 
358   when Array
359     value.each_with_index do |item, index|
360       value[index] = value(item, undefined_value)
361     end
362 
363   when Hash
364     value.each do |key, data|
365       value[key] = value(data, undefined_value)
366     end
367   end
368   return value
369 end