hashstructor 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/hashstructor/instance_methods.rb +51 -0
- data/lib/hashstructor/member.rb +51 -15
- data/lib/hashstructor/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 09a0c03bda60b67da2ec5b83fc21e42b6347bfd9
|
4
|
+
data.tar.gz: 965e9e766544974d6afd2e70a94dc1339cd513f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67d10c1f1d44188d219b2675ede43e3a3b4a7510b2824df4cdf8f808456326f4a7efc5d170ffb44b9886735afc358b7d2346fee8fadf93e838f5680929b07e34
|
7
|
+
data.tar.gz: a5635377333bcd518bf166d0f8e3a2080cbd24c420b241c6a09716e87ee6e1a5ff2e6367674e8ca6eb1ce748e08599d2faeaf85c551d438c9861ad00eb987851
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
There comes a time in every wee programmer's life (and all programmers are, for the purposes of this readme, wee or previously wee) when one must take a big blob of JSON or YAML and make it into an object. Or worse, a hierarchy of objects. This leads to lots of very manual parsing and gnashing of teeth. Some libraries, like the mildly spiffy [constructor](https://github.com/atomicobject/constructor), allow you to defray some of this pain by letting you pass in hashes to build objects, but this only goes so far: no type coercion, no nested types.
|
4
4
|
|
5
|
-
Finally I got tired of this mess when building a game prototype and writing enough stupid read-in code of data files that I decided to Fix This Situation. (You can argue that I got sidetracked; I won't disagree.) After about three hours of late-night work, I'm somewhat proud to unveil **Hashstructor**: your one-stop shop for mangling the heck out of Ruby hashes and building neat-o object trees out of them.
|
5
|
+
Finally I got tired of this mess when building a game prototype and writing enough stupid read-in code of data files that I decided to Fix This Situation. (You can argue that I got sidetracked; I won't disagree.) After about three hours of late-night work, I'm somewhat proud to unveil **Hashstructor**: your one-stop shop for mangling the heck out of Ruby hashes and building neat-o object trees out of them. You can also turn them back into hashes with `#to_hash`--I've found this really useful for transient domain objects in message queues. The creator can create objects with validation and structure and then `#to_hash` them when they go into the queue, and the same can be done when you get them back out.
|
6
6
|
|
7
7
|
Hashstructor is _fully documented_ (100% coverage in `yard`) and comes with a fairly exhaustive set of tests to prove that it actually does what it's supposed to do.
|
8
8
|
|
@@ -3,6 +3,57 @@ require 'set'
|
|
3
3
|
module Hashstructor
|
4
4
|
# Instance methods for {Hashstructor} objects.
|
5
5
|
module InstanceMethods
|
6
|
+
|
7
|
+
|
8
|
+
# Converts the class back to a hash.
|
9
|
+
#
|
10
|
+
# @returns [Hash] the hash representation of this class
|
11
|
+
def to_h
|
12
|
+
to_hash
|
13
|
+
end
|
14
|
+
|
15
|
+
# Converts the class back to a hash.
|
16
|
+
#
|
17
|
+
# @returns [Hash] the hash representation of this class
|
18
|
+
def to_hash
|
19
|
+
hash = {}
|
20
|
+
|
21
|
+
self.class.hashstructor_members.each do |member|
|
22
|
+
member_value = instance_variable_get("@#{member.name}")
|
23
|
+
|
24
|
+
out_value =
|
25
|
+
case member.member_type
|
26
|
+
when :normal
|
27
|
+
member_value.nil? ? nil : member.to_hash_value(member_value)
|
28
|
+
when :array
|
29
|
+
# There's some weird Ruby thing I don't get here, but if I use
|
30
|
+
# a #select instead of an each + container, I end up returning
|
31
|
+
# the actual objects rather than their to_hashes.
|
32
|
+
container = []
|
33
|
+
member_value.each do |v|
|
34
|
+
container << member.to_hash_value(v)
|
35
|
+
end
|
36
|
+
container
|
37
|
+
when :set
|
38
|
+
container = Set.new
|
39
|
+
member_value.each do |v|
|
40
|
+
container << member.to_hash_value(v)
|
41
|
+
end
|
42
|
+
container
|
43
|
+
when :hash
|
44
|
+
container = {}
|
45
|
+
member_value.each do |k, v|
|
46
|
+
container[k] = member.to_hash_value(v)
|
47
|
+
end
|
48
|
+
container
|
49
|
+
end
|
50
|
+
|
51
|
+
hash[member.name.to_sym] = out_value
|
52
|
+
end
|
53
|
+
|
54
|
+
hash
|
55
|
+
end
|
56
|
+
|
6
57
|
private
|
7
58
|
# Initializes the object. This exists for objects that `prepend`
|
8
59
|
# {Hashstructor}; objects that `include` it must explicitly invoke
|
data/lib/hashstructor/member.rb
CHANGED
@@ -51,20 +51,32 @@ module Hashstructor
|
|
51
51
|
# not frozen; if you want to extend it for your own use cases, I'm not
|
52
52
|
# going to get in your way.
|
53
53
|
VALID_VALUE_TYPES = {
|
54
|
-
String =>
|
55
|
-
v
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
54
|
+
String => {
|
55
|
+
:in => Proc.new do |v|
|
56
|
+
v.to_s
|
57
|
+
end
|
58
|
+
},
|
59
|
+
Symbol => {
|
60
|
+
:in => Proc.new do |v|
|
61
|
+
v.to_sym
|
62
|
+
end
|
63
|
+
},
|
64
|
+
Integer => {
|
65
|
+
:in => Proc.new do |v|
|
66
|
+
Integer(v.to_s)
|
67
|
+
end
|
68
|
+
},
|
69
|
+
Float => {
|
70
|
+
:in => Proc.new do |v|
|
71
|
+
Float(v.to_s)
|
72
|
+
end
|
73
|
+
},
|
74
|
+
TrueClass => {
|
75
|
+
:in => BOOL_PROC
|
76
|
+
},
|
77
|
+
FalseClass => {
|
78
|
+
:in => BOOL_PROC
|
79
|
+
},
|
68
80
|
}
|
69
81
|
# Determines the class that Hashstructor should attempt to coerce a
|
70
82
|
# given value into. For example, `Fixnum` will attempt to coerce a
|
@@ -159,7 +171,7 @@ module Hashstructor
|
|
159
171
|
|
160
172
|
value_type.new(value)
|
161
173
|
else
|
162
|
-
VALID_VALUE_TYPES[value_type].call(value)
|
174
|
+
VALID_VALUE_TYPES[value_type][:in].call(value)
|
163
175
|
end
|
164
176
|
|
165
177
|
if options[:validation]
|
@@ -173,5 +185,29 @@ module Hashstructor
|
|
173
185
|
|
174
186
|
retval
|
175
187
|
end
|
188
|
+
|
189
|
+
# The inverse of {#parse_single}, which turns a hashstructed member into a hash value. This should
|
190
|
+
# always be a strict inverse; anything this returns should be able to be fed into {#parse_single}
|
191
|
+
# to return the value passed into this function in the first place.
|
192
|
+
def to_hash_value(member_value)
|
193
|
+
if member_value.class.ancestors.include?(Hashstructor)
|
194
|
+
member_value.to_hash
|
195
|
+
else
|
196
|
+
out_proc = VALID_VALUE_TYPES[value_type][:out]
|
197
|
+
|
198
|
+
if (out_proc && !value_type.nil?)
|
199
|
+
out_proc.call(member_value)
|
200
|
+
else
|
201
|
+
if member_value.respond_to?(:to_h)
|
202
|
+
member_value.to_h
|
203
|
+
elsif member_value.respond_to?(:to_hash)
|
204
|
+
member_value.to_hash
|
205
|
+
else
|
206
|
+
member_value
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
176
212
|
end
|
177
213
|
end
|
data/lib/hashstructor/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hashstructor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ed Ropple
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
124
|
version: '0'
|
125
125
|
requirements: []
|
126
126
|
rubyforge_project:
|
127
|
-
rubygems_version: 2.4.
|
127
|
+
rubygems_version: 2.4.5
|
128
128
|
signing_key:
|
129
129
|
specification_version: 4
|
130
130
|
summary: A Ruby DSL and parser for converting hashes into trees of data objects.
|