hash-proxy 0.0.4 → 0.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.
- data/History.txt +4 -0
- data/README.md +10 -1
- data/lib/hash_proxy/proxy.rb +64 -9
- data/spec/hash_proxy_spec.rb +33 -0
- data/version.txt +1 -1
- metadata +2 -2
data/History.txt
CHANGED
data/README.md
CHANGED
@@ -25,11 +25,20 @@ Features
|
|
25
25
|
Examples
|
26
26
|
--------
|
27
27
|
|
28
|
-
require '
|
28
|
+
require 'hash_proxy'
|
29
29
|
hash = {foo: 'bar', baz: [{key: 'value', key2: 2, key3: [1,2,3]}, {key: 'value2', key2: 22, key3: [4,5,6]}], bip: 'bop'}
|
30
30
|
proxy = HashProxy.create_from(hash)
|
31
31
|
proxy.baz.last.key3.should == [4,5,6]
|
32
32
|
|
33
|
+
Also supports hash like semantics:
|
34
|
+
|
35
|
+
proxy[:foo] => 'bar'
|
36
|
+
proxy[:newkey] = 'new value'
|
37
|
+
|
38
|
+
proxy.each do |k, v|
|
39
|
+
puts "#{k}: #{v}"
|
40
|
+
end
|
41
|
+
|
33
42
|
Requirements
|
34
43
|
------------
|
35
44
|
|
data/lib/hash_proxy/proxy.rb
CHANGED
@@ -5,6 +5,7 @@ module HashProxy
|
|
5
5
|
# hash at the key corresponding to the message. If the
|
6
6
|
# key does not exist, returns a NullObject instance.
|
7
7
|
class Proxy
|
8
|
+
include Enumerable
|
8
9
|
# The one and only NullObject instance
|
9
10
|
NO_OBJECT = NullObject.new
|
10
11
|
|
@@ -24,21 +25,67 @@ module HashProxy
|
|
24
25
|
@converted = {}
|
25
26
|
end
|
26
27
|
|
27
|
-
#
|
28
|
+
# Returns the number of values stored in the underlying hash
|
29
|
+
#
|
30
|
+
# @return [Integer]
|
31
|
+
def size
|
32
|
+
@hash.size + @converted.size
|
33
|
+
end
|
34
|
+
|
35
|
+
# Yields to the provided block all the values in this Hash proxy. All values
|
36
|
+
# are converted via #convert_value as they are yielded. The order in which
|
37
|
+
# values are yielded is not deterministic. Insertion order in the original
|
38
|
+
# hash may be lost if some values are already converted.
|
39
|
+
def each(&blk)
|
40
|
+
enum = Enumerator.new do |y|
|
41
|
+
@converted.each {|k, v| y.yield(k,v) }
|
42
|
+
@hash.each {|k,v| y.yield(k, self.move_value(k)) }
|
43
|
+
end
|
44
|
+
if blk.nil?
|
45
|
+
enum
|
46
|
+
else
|
47
|
+
enum.each do |k,v|
|
48
|
+
blk.call(k,v)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the converted value in the original
|
54
|
+
# hash associated with the given key
|
55
|
+
#
|
56
|
+
# @param [Object] key The value to look up
|
57
|
+
# @return [Object] The object associated with the key
|
58
|
+
def [](key)
|
59
|
+
self.send(key)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sets a value after converting it to a Proxy if necessary
|
63
|
+
#
|
64
|
+
# @param [Object] key The key of the value to set
|
65
|
+
# @param [Object] value The value to set
|
66
|
+
def []=(key, value)
|
67
|
+
self.send("#{key}=", value)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Turns arbitrary method invocations into
|
28
71
|
# lookups or sets on the contained hash
|
29
72
|
def method_missing(name, *args)
|
30
73
|
name_str = name.to_s
|
31
74
|
if name_str.end_with?(EQUALS)
|
32
|
-
|
75
|
+
# Handle edge case (self.send(:"=", 'foo') ? why would someone do this)
|
76
|
+
if name_str != EQUALS
|
77
|
+
@converted[name_str[0..-2].to_sym] = convert_value(args.first)
|
78
|
+
else
|
79
|
+
super
|
80
|
+
end
|
33
81
|
else
|
34
|
-
#
|
35
|
-
|
36
|
-
|
37
|
-
@converted[name_str]
|
82
|
+
# Return the value if it has already been converted
|
83
|
+
if @converted.has_key?(name)
|
84
|
+
@converted[name]
|
38
85
|
else
|
39
|
-
|
40
|
-
|
41
|
-
|
86
|
+
# Move the value from the original hash to the converted hash.
|
87
|
+
# Support both symbol or string keys
|
88
|
+
self.move_value(name, name_str)
|
42
89
|
end
|
43
90
|
end
|
44
91
|
end
|
@@ -80,5 +127,13 @@ module HashProxy
|
|
80
127
|
value || NO_OBJECT
|
81
128
|
end
|
82
129
|
end
|
130
|
+
|
131
|
+
# moves a value from the original hash to the converted
|
132
|
+
# hash after converting the value to a proxy if necessary
|
133
|
+
def move_value(name, name_str = name.to_s)
|
134
|
+
@converted[name] = self.convert_value(@hash.delete(name) || @hash.delete(name_str))
|
135
|
+
end
|
136
|
+
|
83
137
|
end
|
138
|
+
|
84
139
|
end
|
data/spec/hash_proxy_spec.rb
CHANGED
@@ -2,6 +2,39 @@
|
|
2
2
|
require File.expand_path('../spec_helper', __FILE__)
|
3
3
|
|
4
4
|
describe HashProxy do
|
5
|
+
it "supports enumerable" do
|
6
|
+
hash = {foo: 'bar', baz: 'bip', smee: 'cree'}
|
7
|
+
proxy = HashProxy::Proxy.new(hash)
|
8
|
+
iterator = proxy.each
|
9
|
+
iterator.to_a.should eq([[:foo, 'bar'], [:baz, 'bip'], [:smee, 'cree']])
|
10
|
+
|
11
|
+
proxy.take(1).should eq([[:foo, 'bar']])
|
12
|
+
end
|
13
|
+
|
14
|
+
it "behaves kind of like a hash" do
|
15
|
+
hash = {foo: 'bar', baz: 'bip', smee: 'cree'}
|
16
|
+
proxy = HashProxy::Proxy.new(hash)
|
17
|
+
proxy.size.should eq(3)
|
18
|
+
proxy.each.to_a.size.should eq(3)
|
19
|
+
proxy.each.to_a.map{|a| a.first}.should eq([:foo, :baz, :smee])
|
20
|
+
proxy.each.to_a.map{|a| a.last}.should eq(['bar', 'bip', 'cree'])
|
21
|
+
proxy[:foo].should eq('bar')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can call setters" do
|
25
|
+
proxy = HashProxy::Proxy.new({})
|
26
|
+
proxy.foo = 'foo val'
|
27
|
+
proxy.bar = {:bip => :baz, :smoo => :smee}
|
28
|
+
|
29
|
+
proxy.size.should eq(2)
|
30
|
+
proxy[:bar].class.should eq(HashProxy::Proxy)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "handles crappy method calls" do
|
34
|
+
proxy = HashProxy::Proxy.new({})
|
35
|
+
lambda { proxy.send(:'=', 'crap') }.should raise_error(NoMethodError)
|
36
|
+
end
|
37
|
+
|
5
38
|
it "turns hash keys into method calls" do
|
6
39
|
hash = {foo: 'bar', baz: 'bip'}
|
7
40
|
proxy = HashProxy::Proxy.new(hash)
|
data/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hash-proxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bones
|