Class: DataStruct
- Inherits:
-
Object
- Object
- DataStruct
- Defined in:
- lib/datastruct.rb
Constant Summary collapse
- VERSION =
"0.0.6"
Class Method Summary collapse
-
.from_array(array) ⇒ Object
A more ideomatic way of calling new(*array).
-
.from_hash(hash) ⇒ Object
A more ideomatic way of calling new(**hash).
-
.new(*args, &block) ⇒ Object
Makes sure @data is set before
initialize
is called.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Delegates to Hash#==.
-
#[](key) ⇒ Object
Does the same as
#get
, but returns nil instead of raisingKeyError
. -
#dup ⇒ Object
Returns a shallow copy.
-
#each ⇒ Object
Delegates to Hash#each.
-
#get(property) ⇒ Object
Returns a property using its getter method.
-
#initialize(*args, **kwargs) ⇒ DataStruct
constructor
A new instance of DataStruct.
-
#inspect ⇒ Object
Produces a text representation of the object.
-
#merge(other) ⇒ Hash
Delegates to Hash#merge.
- #respond_to?(method_name) ⇒ Boolean
-
#set(property, value) ⇒ Object
(also: #[]=)
Sets the value of a property using its setter method.
-
#to_array ⇒ Array
(also: #to_a)
Returns the properties of the object as an array.
-
#to_hash(string_keys: false, deep: false) ⇒ Hash
(also: #to_h)
Returns the properties of the object as a hash.
-
#to_json(*args) ⇒ String
Dumps the properties of this object to JSON using Ruby’s JSON module.
-
#to_yaml(*args) ⇒ String
Dumps the properties of this object to YAML using Ruby’s YAML module.
-
#update(*args, **kwargs) ⇒ Object
Updates the values of this object’s properties.
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
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/datastruct.rb', line 290 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
113 114 115 116 117 |
# File 'lib/datastruct.rb', line 113 def [](key) get(key) rescue KeyError nil end |
#dup ⇒ Object
Returns a shallow copy
87 88 89 |
# File 'lib/datastruct.rb', line 87 def dup self.class.from_hash(@data.dup) end |
#each ⇒ Object
Delegates to Hash#each
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
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 |
#inspect ⇒ Object
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 << self.class::PROPERTIES.reduce("") { |a, key| a << " #{key}=#{self.get(key).inspect}" } text << ">" return text end |
#merge(other) ⇒ Hash
Delegates to Hash#merge
277 278 279 |
# File 'lib/datastruct.rb', line 277 def merge(other) @data.merge(other) end |
#respond_to?(method_name) ⇒ 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
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_array ⇒ Array Also known as: to_a
Returns the properties of the object as an 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, deep: false) ⇒ Hash Also known as: to_h
Returns the properties of the object as a hash
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/datastruct.rb', line 180 def to_hash(string_keys: false, deep: false) # Builds a hash using property getters. This allows getters to override the # output of this function. data = Hash[self.class::PROPERTIES.map { |key| [key, self.get(key)] }] hashify = lambda { |obj| if obj.is_a? DataStruct and deep return obj.to_hash(string_keys: string_keys, deep: deep) elsif obj.is_a? Hash out = {} obj.each_pair { |key, value| # Only stringify the keys of the *top level* of the structure. We have # no business messing with the keys of nested hashes. key = key.to_s if string_keys and obj.equal? data out[key] = hashify[value] } return out elsif obj.is_a? Array return obj.map { |x| hashify[x] } else return obj end } return data if not string_keys and not deep return hashify[data] end |
#to_json(*args) ⇒ String
JSON must be loaded for this function to work
Dumps the properties of this object to JSON using Ruby’s JSON module
223 224 225 |
# File 'lib/datastruct.rb', line 223 def to_json(*args) self.to_hash.to_json(*args) end |
#to_yaml(*args) ⇒ String
YAML must be loaded for this function to work
Dumps the properties of this object to YAML using Ruby’s YAML module
234 235 236 |
# File 'lib/datastruct.rb', line 234 def to_yaml(*args) self.to_hash.to_yaml(*args) end |
#update(*args, **kwargs) ⇒ Object
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.
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/datastruct.rb', line 249 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 |