hash-proxy 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|