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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53417f9ad796f3bdbadd248016ebb1aed623160c
4
- data.tar.gz: 0a653553b55d4d333bc0be0d4d53d337beb7b7a5
3
+ metadata.gz: 09a0c03bda60b67da2ec5b83fc21e42b6347bfd9
4
+ data.tar.gz: 965e9e766544974d6afd2e70a94dc1339cd513f1
5
5
  SHA512:
6
- metadata.gz: 2f2ffb6a2a38ea3577dc2352d017af7b57f0ba5a4ada604703c4b500859b0ccb5c18328801e3a11555c9c4fd93d8792b2dcb18178723e3daf61c0c018ea21ec6
7
- data.tar.gz: 88e18912f12e341dc4427b015c6e594b9990e78f227d8cdc167ddf8f3d4f9d84b18089549d00546bc0d76bf1358b4de27670fc846c78478cf44e2beefa706af1
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. (The reverse, breaking these data structures down into hashes, is a TODO.)
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
@@ -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 => Proc.new do |v|
55
- v.to_s
56
- end,
57
- Symbol => Proc.new do |v|
58
- v.to_sym
59
- end,
60
- Integer => Proc.new do |v|
61
- Integer(v.to_s)
62
- end,
63
- Float => Proc.new do |v|
64
- Float(v.to_s)
65
- end,
66
- TrueClass => BOOL_PROC,
67
- FalseClass => BOOL_PROC,
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
@@ -1,4 +1,4 @@
1
1
  module Hashstructor
2
2
  # The gem version. As one does.
3
- VERSION = "1.0.6"
3
+ VERSION = "1.1.0"
4
4
  end
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.6
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-07-23 00:00:00.000000000 Z
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.6
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.