Class: DataStruct

Inherits:
Object
  • Object
show all
Defined in:
lib/datastruct.rb

Constant Summary collapse

VERSION =
"0.0.5"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, **kwargs) ⇒ DataStruct

Returns a new instance of DataStruct.



58
59
60
61
# File 'lib/datastruct.rb', line 58

def initialize(*args, **kwargs)
  self.update(*args)
  self.update(**kwargs)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object (private)

This makes the struct accept the defined properties as instance methods



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/datastruct.rb', line 261

def method_missing(name, *args, &block)
  property = name
  set = false

  if is_setter?(property)
    property = getter(name)
    set = true
  end

  if valid_property? property
    if set
      @data[property] = args.first
    else
      @data[property]
    end
  else
    super
  end
end

Class Method Details

.from_array(array) ⇒ Object

A more ideomatic way of calling new(*array)



45
46
47
# File 'lib/datastruct.rb', line 45

def self.from_array(array)
  self.new(*array)
end

.from_hash(hash) ⇒ Object

A more ideomatic way of calling new(**hash)



52
53
54
55
56
# File 'lib/datastruct.rb', line 52

def self.from_hash(hash)
  hash = symbol_keys(hash)

  self.new(**hash)
end

.new(*args, &block) ⇒ Object

Makes sure @data is set before initialize is called

The @data instance variable is set to a hash with each key in PROPERTIES set to nil before the constructor is called. This avoids a host of annoying issues when users override the constructor.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/datastruct.rb', line 23

def self.new(*args, &block)
  instance = allocate()

  data_container = {}

  if instance.class.const_defined? :PROPERTIES
    properties = instance.class::PROPERTIES
  else
    properties = []
  end

  properties.each { |key| data_container[key] = nil }
  instance.instance_variable_set(:@data, data_container)

  instance.send(:initialize, *args, &block)

  return instance
end

Instance Method Details

#==(other) ⇒ Object

Delegates to Hash#==



66
67
68
69
70
71
72
# File 'lib/datastruct.rb', line 66

def ==(other)
  if not other.instance_of? self.class
    false
  else
    @data == other.instance_variable_get(:@data)
  end
end

#[](key) ⇒ Object

Does the same as #get, but returns nil instead of raising KeyError

Parameters:

  • key (String, Symbol)

Returns:

  • (Object)


113
114
115
116
117
# File 'lib/datastruct.rb', line 113

def [](key)
  get(key)
rescue KeyError
  nil
end

#dupObject

Returns a shallow copy



87
88
89
# File 'lib/datastruct.rb', line 87

def dup
  self.class.from_hash(@data.dup)
end

#eachObject

Delegates to Hash#each

See Also:



80
81
82
# File 'lib/datastruct.rb', line 80

def each(*args, &block)
  @data.each(*args, &block)
end

#get(property) ⇒ Object

Returns a property using its getter method

Parameters:

  • property (String, Symbol)

Raises:

  • (KeyError)

    on invalid property name



97
98
99
100
101
102
103
104
105
# File 'lib/datastruct.rb', line 97

def get(property)
  property = property.to_sym

  if not valid_property? property
    fail KeyError, "Property not defined: #{property}"
  end

  self.send(property)
end

#inspectObject

Produces a text representation of the object



122
123
124
125
126
127
128
129
130
131
132
# File 'lib/datastruct.rb', line 122

def inspect
  text = "#<#{self.class.to_s}"

  text << @data.reduce("") { |a, pair|
    a << " #{pair[0]}=#{pair[1].inspect}"
  }

  text << ">"

  return text
end

#merge(other) ⇒ Hash

Delegates to Hash#merge

Returns:

  • (Hash)


248
249
250
# File 'lib/datastruct.rb', line 248

def merge(other)
  @data.merge(other)
end

#respond_to?(method_name) ⇒ Boolean

Returns:

  • (Boolean)


134
135
136
137
138
139
140
# File 'lib/datastruct.rb', line 134

def respond_to?(method_name)
  if valid_property?(method_name) or valid_property?(getter(method_name))
    true
  else
    super
  end
end

#set(property, value) ⇒ Object Also known as: []=

Sets the value of a property using its setter method

Parameters:

  • property (String, Symbol)
  • value (Object)

Raises:

  • (KeyError)

    on invalid property name



149
150
151
152
153
154
155
156
157
# File 'lib/datastruct.rb', line 149

def set(property, value)
  property = property.to_sym

  if not valid_property? property
    fail KeyError, "Property not defined: #{property}"
  end

  self.send(setter(property), value)
end

#to_arrayArray Also known as: to_a

Returns the properties of the object as an array

Returns:

  • (Array)


166
167
168
# File 'lib/datastruct.rb', line 166

def to_array
  self.class::PROPERTIES.map { |name| @data[name] }
end

#to_hash(string_keys: false) ⇒ Hash Also known as: to_h

Returns the properties of the object as a hash

Returns:

  • (Hash)


177
178
179
180
181
182
183
# File 'lib/datastruct.rb', line 177

def to_hash(string_keys: false)
  if string_keys
    Hash[@data.to_a.map { |key, value| [key.to_s, value] }]
  else
    @data.dup
  end
end

#to_json(*args) ⇒ String

Note:

JSON must be loaded for this function to work

Dumps the properties of this object to JSON using Ruby’s JSON module

Returns:

  • (String)

See Also:



194
195
196
# File 'lib/datastruct.rb', line 194

def to_json(*args)
  @data.to_json(*args)
end

#to_yaml(*args) ⇒ String

Note:

YAML must be loaded for this function to work

Dumps the properties of this object to YAML using Ruby’s YAML module

Returns:

  • (String)

See Also:



205
206
207
# File 'lib/datastruct.rb', line 205

def to_yaml(*args)
  @data.to_yaml(*args)
end

#update(*args, **kwargs) ⇒ Object

Note:

Keyword arguments override posisional arguments

Updates the values of this object’s properties

Both positional arguments and keyword arguments are used to update the property values of the object. Positional arguments should be passed in the same order as the defined properties.

Returns:

  • nil

Raises:

  • (ArgumentError)

    on invalid property names



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/datastruct.rb', line 220

def update(*args, **kwargs)
  if args.length > self.class::PROPERTIES.length
    x = args.length
    y = self.class::PROPERTIES.length
    msg = "Too many arguments (you passed #{x} arguments for #{y} properties)"

    fail ArgumentError, msg
  end

  hash = Hash[self.class::PROPERTIES[0...args.length].zip(args)]
  hash.update(kwargs)

  hash.each_pair { |key, value|
    begin
      self.set(key, value)
    rescue KeyError => e
      fail ArgumentError, "Invalid property: #{key}"
    end
  }

  nil
end