class Functional::ValueStruct
A variation on Ruby’s ‘OpenStruct` in which all fields are immutable and set at instantiation. For compatibility with {Functional::FinalStruct}, predicate methods exist for all potential fields and these predicates indicate if the field has been set. Calling a predicate method for a field that does not exist on the struct will return false.
Unlike {Functional::Record}, which returns a new class which can be used to create immutable objects, ‘ValueStruct` creates simple immutable objects.
@example Instanciation
name = Functional::ValueStruct.new(first: 'Douglas', last: 'Adams') name.first #=> 'Douglas' name.last #=> 'Adams' name.first? #=> true name.last? #=> true name.middle? #=> false
@see Functional::Record
@see Functional::FinalStruct
@see www.ruby-doc.org/stdlib-2.1.2/libdoc/ostruct/rdoc/OpenStruct.html
@!macro thread_safe_immutable_object
Public Class Methods
Functional::Synchronization::Object::new
# File lib/functional/value_struct.rb, line 30 def initialize(attributes) raise ArgumentError.new('attributes must be given as a hash') unless attributes.respond_to?(:each_pair) super @attribute_hash = {} attributes.each_pair do |field, value| set_attribute(field, value) end @attribute_hash.freeze ensure_ivar_visibility! self.freeze end
Public Instance Methods
Calls the block once for each attribute, passing the key/value pair as parameters. If no block is given, an enumerator is returned instead.
@yieldparam [Symbol] field the struct field for the current iteration @yieldparam [Object] value the value of the current field
@return [Enumerable] when no block is given
# File lib/functional/value_struct.rb, line 77 def each_pair return enum_for(:each_pair) unless block_given? @attribute_hash.each do |field, value| yield(field, value) end end
Compares this object and other for equality. A ‘ValueStruct` is `eql?` to other when other is a `ValueStruct` and the two objects have identical fields and values.
@param [Object] other the other record to compare for equality @return [Boolean] true when equal else false
# File lib/functional/value_struct.rb, line 98 def eql?(other) other.is_a?(self.class) && @attribute_hash == other.to_h end
Get the current value of the given field if already set else return the given default value.
@param [Symbol] field the field to get the value for @param [Object] default the value to return if the field has not been set @return [Object] the value of the given field else the given default value
# File lib/functional/value_struct.rb, line 66 def fetch(field, default) @attribute_hash.fetch(field.to_sym, default) end
Get the value of the given field.
@param [Symbol] field the field to retrieve the value for @return [Object] the value of the field is set else nil
# File lib/functional/value_struct.rb, line 46 def get(field) @attribute_hash[field.to_sym] end
Describe the contents of this object in a string.
@return [String] the string representation of this object
@!visibility private
# File lib/functional/value_struct.rb, line 108 def inspect state = @attribute_hash.to_s.gsub(/^{/, '').gsub(/}$/, '') "#<#{self.class} #{state}>" end
Check the internal hash to unambiguously verify that the given attribute has been set.
@param [Symbol] field the field to get the value for @return [Boolean] true if the field has been set else false
# File lib/functional/value_struct.rb, line 56 def set?(field) @attribute_hash.has_key?(field.to_sym) end
Converts the ‘ValueStruct` to a `Hash` with keys representing each attribute (as symbols) and their corresponding values.
@return [Hash] a ‘Hash` representing this struct
# File lib/functional/value_struct.rb, line 88 def to_h @attribute_hash.dup # dup removes the frozen flag end
Protected Instance Methods
Check the method name and args for signatures matching potential final predicate methods. If the signature matches call the appropriate method
@param [Symbol] symbol the name of the called function @param [Array] args zero or more arguments @return [Object] the result of the proxied method or the ‘super` call
@!visibility private
# File lib/functional/value_struct.rb, line 136 def method_missing(symbol, *args) if args.length == 0 && (match = /([^\?]+)\?$/.match(symbol)) set?(match[1]) elsif args.length == 0 && set?(symbol) get(symbol) else super end end
Set the value of the give field to the given value.
@param [Symbol] field the field to set the value for @param [Object] value the value to set the field to @return [Object] the final value of the given field
@!visibility private
# File lib/functional/value_struct.rb, line 123 def set_attribute(field, value) @attribute_hash[field.to_sym] = value end