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.



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/jsi/util/private/attr_struct.rb', line 68

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| class_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>)


54
55
56
57
# File 'lib/jsi/util/private/attr_struct.rb', line 54

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.



62
63
64
65
# File 'lib/jsi/util/private/attr_struct.rb', line 62

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
43
44
45
46
47
48
# File 'lib/jsi/util/private/attr_struct.rb', line 18

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

  attribute_keys = attribute_keys.map { |key| convert_key(key) }

  bad_name = attribute_keys.reject { |key| Util::Private.ok_ruby_method_name?(key) }
  unless bad_name.empty?
    raise(ArgumentError, "attribute keys must be valid ruby method names; got keys: #{bad_name.map(&:inspect).join(', ')}")
  end

  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.



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

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.



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

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

#class_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>)


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

def class_attribute_keys
  self.class.attribute_keys
end

#freezeObject

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.



127
128
129
130
# File 'lib/jsi/util/private/attr_struct.rb', line 127

def freeze
  @attributes.freeze
  super
end

#inspectString

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)


95
96
97
# File 'lib/jsi/util/private/attr_struct.rb', line 95

def inspect
  -"\#<#{self.class.name}#{@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.

see FingerprintHash



136
137
138
# File 'lib/jsi/util/private/attr_struct.rb', line 136

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

#pretty_print(q)

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



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/jsi/util/private/attr_struct.rb', line 105

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

#to_sObject

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.



99
100
101
# File 'lib/jsi/util/private/attr_struct.rb', line 99

def to_s
  inspect
end