Class: JSI::Util::Private::AttrStruct Private

Inherits:
Object
  • Object
show all
Includes:
FingerprintHash
Defined in:
lib/jsi/util/private/attr_struct.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

like a Struct, but stores all the attributes in one @attributes Hash, instead of individual instance variables for each attribute. this tends to be easier to work with and more flexible. keys which are symbols are converted to strings.

Defined Under Namespace

Classes: AttrStructError, UndefinedAttributeKey

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FingerprintHash

#==, #hash

Constructor Details

#initialize(attributes = {}) ⇒ AttrStruct

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of AttrStruct.



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/jsi/util/private/attr_struct.rb', line 62

def initialize(attributes = {})
  unless attributes.respond_to?(:to_hash)
    raise(TypeError, "expected attributes to be a Hash; got: #{attributes.inspect}")
  end
  @attributes = {}
  attributes.to_hash.each do |k, v|
    @attributes[self.class.convert_key(k)] = v
  end
  bad = @attributes.keys.reject { |k| attribute_keys.include?(k) }
  unless bad.empty?
    raise UndefinedAttributeKey, "undefined attribute keys: #{bad.map(&:inspect).join(', ')}"
  end
end

Class Method Details

.attribute_keysSet<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

the attribute keys defined for this class

Returns:

  • (Set<String>)


48
49
50
51
# File 'lib/jsi/util/private/attr_struct.rb', line 48

def attribute_keys
  # empty for AttrStruct itself; redefined on each subclass
  Util::Private::EMPTY_SET
end

.convert_key(key) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

returns a frozen string, given a string or symbol. returns anything else as-is for the caller to handle.



56
57
58
59
# File 'lib/jsi/util/private/attr_struct.rb', line 56

def convert_key(key)
  # TODO use Symbol#name when available on supported rubies
  key.is_a?(Symbol) ? key.to_s.freeze : key.frozen? ? key : key.is_a?(String) ? key.dup.freeze : key
end

.subclass(*attribute_keys) ⇒ Object Also known as: []

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

creates a AttrStruct subclass with the given attribute keys.

Parameters:

  • attribute_keys (Enumerable<String, Symbol>)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/jsi/util/private/attr_struct.rb', line 18

def subclass(*attribute_keys)
  bad = attribute_keys.reject { |key| key.respond_to?(:to_str) || key.is_a?(Symbol) }
  unless bad.empty?
    raise ArgumentError, "attribute keys must be String or Symbol; got keys: #{bad.map(&:inspect).join(', ')}"
  end
  attribute_keys = attribute_keys.map { |key| convert_key(key) }

  all_attribute_keys = (self.attribute_keys + attribute_keys).freeze

  Class.new(self).tap do |klass|
    klass.define_singleton_method(:attribute_keys) { all_attribute_keys }

    attribute_keys.each do |attribute_key|
      # reader
      klass.send(:define_method, attribute_key) do
        @attributes[attribute_key]
      end

      # writer
      klass.send(:define_method, "#{attribute_key}=") do |value|
        @attributes[attribute_key] = value
      end
    end
  end
end

Instance Method Details

#[](key) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



76
77
78
# File 'lib/jsi/util/private/attr_struct.rb', line 76

def [](key)
  @attributes[key.is_a?(Symbol) ? key.to_s : key]
end

#[]=(key, value) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



80
81
82
83
84
85
86
# File 'lib/jsi/util/private/attr_struct.rb', line 80

def []=(key, value)
  key = self.class.convert_key(key)
  unless attribute_keys.include?(key)
    raise UndefinedAttributeKey, "undefined attribute key: #{key.inspect}"
  end
  @attributes[key] = value
end

#attribute_keysSet<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

the attribute keys defined for this class

Returns:

  • (Set<String>)


117
118
119
# File 'lib/jsi/util/private/attr_struct.rb', line 117

def attribute_keys
  self.class.attribute_keys
end

#inspectString Also known as: to_s

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (String)


89
90
91
# File 'lib/jsi/util/private/attr_struct.rb', line 89

def inspect
  "\#<#{self.class.name}#{@attributes.empty? ? '' : ' '}#{@attributes.map { |k, v| "#{k}: #{v.inspect}" }.join(', ')}>"
end

#jsi_fingerprintObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



122
123
124
# File 'lib/jsi/util/private/attr_struct.rb', line 122

def jsi_fingerprint
  {class: self.class, attributes: @attributes}
end

#pretty_print(q) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

pretty-prints a representation of self to the given printer



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/jsi/util/private/attr_struct.rb', line 97

def pretty_print(q)
  q.text '#<'
  q.text self.class.name
  q.group_sub {
    q.nest(2) {
      q.breakable(@attributes.empty? ? '' : ' ')
      q.seplist(@attributes, nil, :each_pair) { |k, v|
        q.group {
          q.text k
          q.text ': '
          q.pp v
        }
      }
    }
  }
  q.breakable ''
  q.text '>'
end