class Nucleon::Util::Data
Data
utilities¶ ↑
The Nucleon::Util::Data
class defines various tools for working with data in the Nucleon
system.
It implements:
-
Type checkers
-
Basic data translators
-
Data
transformations -
Other utilities
Public Class Methods
Ensure a data object is an array.
It converts:
-
Symbols to arrays
-
Strings to arrays
-
Splits strings on commas (if split_string requested)
-
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 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:
-
::deep_clean
(recursive clean)
# 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
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
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:
-
::clean
(shallow clean)
# 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
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 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
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
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
-
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
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
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:
-
::array
Ensure result is an array (non arrays are converted) -
::hash
Ensure result is a hash (non hashes are converted) -
::string
Ensure result is a string (non strings are converted) -
::symbol
Ensure result is a symbol (non symbols are converted) -
::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
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 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
-
Returns
- String,
Hash
-
Returns interpolated string or hash of strings
- String,
-
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 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
- nil, String, Symbol, Array,
-
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 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
- nil, true, false, String, Array,
-
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 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
- nil, true, false, String, Array,
-
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 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
-
Returns
- String, Symbol, Array,
Hash
-
Returns prefixed data object
- String, Symbol, Array,
-
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
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
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
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
-
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
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
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
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
-
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 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
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
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
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
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
Translate a value to internally standardized form.
It currently translates:
-
::undef?
to undefined_value -
::true?
to true -
::false?
to false -
Array (recursively)
-
Hash
(recursively)
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