class Struct

Pure Ruby re-implementation of Struct to ensure cross-Ruby functionality where needed (e.g. Opal)

Struct class object instances store members in @members Array and member values in @member_values Hash

API perfectly matches that of Native Ruby built-in Struct.

Native Ruby built-in Struct implementation is aliased as NativeStruct

Constants

ARG_VALIDATION
CLASS_DEFINITION_FOR_ATTRIBUTES
CLASS_NAME_EXTRACTION

Public Class Methods

__new__(class_name_or_attribute, *attributes, keyword_init: false)
Alias for: new
new(class_name_or_attribute, *attributes, keyword_init: false) click to toggle source
# File lib/pure-struct.rb, line 40
def new(class_name_or_attribute, *attributes, keyword_init: false)
  raise 'Arguments cannot be nil' if ARG_VALIDATION[class_name_or_attribute, *attributes]
  class_name = CLASS_NAME_EXTRACTION[class_name_or_attribute]
  attributes.unshift(class_name_or_attribute) if class_name.nil?
  attributes = attributes.map(&:to_sym)
  struct_class = Class.new(self, &CLASS_DEFINITION_FOR_ATTRIBUTES[attributes, keyword_init])
  class_name.nil? ? struct_class : const_set(class_name, struct_class)
end
Also aliased as: __new__

Public Instance Methods

==(other) click to toggle source
# File lib/pure-struct.rb, line 189
def ==(other)
  other = coerce(other).first if respond_to?(:coerce, true)
  other.kind_of?(self.class) &&
    @members.all? { |key| (self[key].equal?(self) && other[key].equal?(self)) || self[key] == other[key] }
end
[](attribute) click to toggle source
# File lib/pure-struct.rb, line 120
def [](attribute)
  normalized_attribute = attribute.to_sym
  raise NameError, "no member #{attribute} in struct" unless @members.include?(normalized_attribute)
  @member_values[normalized_attribute]
end
[]=(attribute, value) click to toggle source
# File lib/pure-struct.rb, line 114
def []=(attribute, value)
  normalized_attribute = attribute.to_sym
  raise NameError, "no member #{attribute} in struct" unless @members.include?(normalized_attribute)
  @member_values[normalized_attribute] = value
end
__inspect__()

Original Object inspect implementation

Alias for: inspect
dig(*args) click to toggle source
# File lib/pure-struct.rb, line 175
def dig(*args)
  @member_values.dig(*args)
end
each(&block) click to toggle source

Iterates through each value

# File lib/pure-struct.rb, line 127
def each(&block)
  to_a.each(&block)
end
each_pair(&block) click to toggle source

Iterates through each member value pair

# File lib/pure-struct.rb, line 132
def each_pair(&block)
  @member_values.each_pair(&block)
end
eql?(other) click to toggle source
# File lib/pure-struct.rb, line 184
def eql?(other)
  instance_of?(other.class) &&
    @members.all? { |key| (self[key].equal?(self) && other[key].equal?(self)) || self[key].eql?(other[key]) }
end
hash() click to toggle source

Return compound hash value consisting of Struct class hash and all indexed value hashes

Opal doesn't implement hash as Integer everywhere, returning strings as themselves, so this returns a String in Opal as a safe common denominator for all object types.

# File lib/pure-struct.rb, line 199
def hash
  return __hash__opal__ if RUBY_ENGINE == 'opal'
  class_hash = self.class.hash
  indexed_values = to_a.each_with_index
  value_hashes = indexed_values.map do |value, i|
    value_hash = value.equal?(self) ? class_hash : value.hash
    i+1 * value_hash
  end
  class_hash + value_hashes.sum
end
inspect()
Also aliased as: __inspect__
Alias for: to_s
length()
Alias for: size
members() click to toggle source

Returns member symbols (strings in Opal) representing Struct attribute names

# File lib/pure-struct.rb, line 110
def members
  (@members ||= self.class.class_variable_get(:@@attributes)).clone
end
select(&block) click to toggle source

Selects values with block (only value is passed in as block arg)

# File lib/pure-struct.rb, line 180
def select(&block)
  to_a.select(&block)
end
size() click to toggle source
# File lib/pure-struct.rb, line 170
def size
  @members.size
end
Also aliased as: length
to_a() click to toggle source

Returns values Array (no member keys)

# File lib/pure-struct.rb, line 142
def to_a
  @member_values.values
end
to_h() click to toggle source

Returns member values Hash (includes member keys)

# File lib/pure-struct.rb, line 137
def to_h
  @member_values.clone
end
to_s() click to toggle source

Prints Struct member values including class name if set

inspect does the same thing

__inspect__ aliases the original Object inspect implementation

# File lib/pure-struct.rb, line 155
def to_s
  member_values_string = @member_values.map do |member, value|
    if value.equal?(self)
      value_class_string = self.class.send(:__inspect__).split.first
      value_string = "#<struct #{value_class_string}:...>"
    else
      value_string = value.inspect
    end
    "#{member}=#{value_string}"
  end.join(', ')
  class_name_string = "#{self.class.name} " unless self.class.name.nil?
  "#<struct #{class_name_string}#{member_values_string}>"
end
Also aliased as: inspect

Private Instance Methods

__hash__opal__() click to toggle source
# File lib/pure-struct.rb, line 212
def __hash__opal__
  class_hash = self.class.hash
  indexed_values = to_a.each_with_index
  class_hash = class_hash.to_s
  value_hashes = indexed_values.map do |value, i|
    value_hash_string = value.equal?(self) ? class_hash : value.hash.to_s
    (i+1).to_s + value_hash_string
  end
  class_hash + value_hashes.reduce(:+)
end