newbamboo-hash_mapper 0.0.5 → 0.0.6
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/README.rdoc +3 -3
- data/lib/hash_mapper.rb +52 -39
- data/spec/hash_mapper_spec.rb +49 -6
- metadata +4 -2
data/README.rdoc
CHANGED
@@ -201,8 +201,8 @@ They all yield a block with 2 arguments - the hash you are mapping from and the
|
|
201
201
|
map from('/raw'), to('/fried')
|
202
202
|
|
203
203
|
before_normalize do |input, output|
|
204
|
-
|
205
|
-
|
204
|
+
input['raw'] ||= 'please' # this will give 'raw' a default value
|
205
|
+
input
|
206
206
|
end
|
207
207
|
|
208
208
|
after_denormalize do |input, output|
|
@@ -211,7 +211,7 @@ They all yield a block with 2 arguments - the hash you are mapping from and the
|
|
211
211
|
|
212
212
|
end
|
213
213
|
|
214
|
-
Important: note that you need to return the
|
214
|
+
Important: note that for before filters, you need to return the (modified) input, and for after filters, you need to return the output.
|
215
215
|
Note also that 'output' is correct at the time of the filter, i.e. before_normalize yields 'output' as an empty hash, while after_normalize yields it as an already normalized hash.
|
216
216
|
|
217
217
|
|
data/lib/hash_mapper.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__)) unless
|
2
2
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
3
|
|
4
|
+
begin
|
5
|
+
require 'active_support'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'active_support'
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
|
4
13
|
# This allows us to call blah(&:some_method) instead of blah{|i| i.some_method }
|
5
14
|
unless Symbol.instance_methods.include?('to_proc')
|
6
15
|
class Symbol
|
@@ -10,11 +19,26 @@ unless Symbol.instance_methods.include?('to_proc')
|
|
10
19
|
end
|
11
20
|
end
|
12
21
|
|
22
|
+
# http://rpheath.com/posts/341-ruby-inject-with-index
|
23
|
+
unless Array.instance_methods.include?("inject_with_index")
|
24
|
+
module Enumerable
|
25
|
+
def inject_with_index(injected)
|
26
|
+
each_with_index{ |obj, index| injected = yield(injected, obj, index) }
|
27
|
+
injected
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
13
32
|
module HashMapper
|
14
|
-
VERSION = '0.0.
|
33
|
+
VERSION = '0.0.6'
|
15
34
|
|
16
|
-
|
17
|
-
|
35
|
+
# we need this for inheritable mappers, which is annoying because it needs ActiveSupport, kinda overkill.
|
36
|
+
#
|
37
|
+
def self.extended(base)
|
38
|
+
base.class_eval do
|
39
|
+
write_inheritable_attribute :maps, []
|
40
|
+
class_inheritable_accessor :maps
|
41
|
+
end
|
18
42
|
end
|
19
43
|
|
20
44
|
def map(from, to, using=nil, &filter)
|
@@ -57,14 +81,15 @@ module HashMapper
|
|
57
81
|
def after_denormalize(&blk)
|
58
82
|
@after_denormalize = blk
|
59
83
|
end
|
60
|
-
|
84
|
+
|
61
85
|
protected
|
86
|
+
|
62
87
|
|
63
88
|
def perform_hash_mapping(a_hash, meth)
|
64
89
|
output = {}
|
65
90
|
# Before filter
|
66
91
|
before_filter = instance_eval "@before_#{meth}"
|
67
|
-
|
92
|
+
a_hash = before_filter.call(a_hash, output) if before_filter
|
68
93
|
# Do the mapping
|
69
94
|
a_hash = symbolize_keys(a_hash)
|
70
95
|
maps.each do |m|
|
@@ -109,50 +134,35 @@ module HashMapper
|
|
109
134
|
|
110
135
|
def get_value_from_input(output, input, path, meth)
|
111
136
|
value = path.inject(input) do |h,e|
|
112
|
-
throw :no_value
|
113
|
-
|
114
|
-
#h[e[0].to_sym]
|
137
|
+
throw :no_value if h[e].nil?#.has_key?(e)
|
138
|
+
h[e]
|
115
139
|
end
|
116
|
-
|
117
|
-
value
|
140
|
+
delegated_mapper ? delegate_to_nested_mapper(value, meth) : value
|
118
141
|
end
|
119
142
|
|
120
143
|
|
121
144
|
def delegate_to_nested_mapper(value, meth)
|
122
|
-
|
145
|
+
case value
|
146
|
+
when Array
|
123
147
|
value.map {|h| delegated_mapper.send(meth, h)}
|
148
|
+
when nil
|
149
|
+
throw :no_value
|
124
150
|
else
|
125
151
|
delegated_mapper.send(meth, value)
|
126
152
|
end
|
127
153
|
end
|
128
154
|
|
129
155
|
def add_value_to_hash!(hash, path, value)
|
130
|
-
path.
|
131
|
-
if
|
132
|
-
|
133
|
-
h[e[0].to_sym]
|
134
|
-
else
|
135
|
-
if e == path.last
|
136
|
-
h[e[0].to_sym][e[1].to_i] = value
|
137
|
-
end
|
138
|
-
h[e[0].to_sym][e[1].to_i]
|
139
|
-
end
|
156
|
+
path.inject_with_index(hash) do |h,e,i|
|
157
|
+
if h[e]
|
158
|
+
h[e]
|
140
159
|
else
|
141
|
-
|
142
|
-
h[e[0].to_sym] = (e == path.last ? path.apply_filter(value) : {})
|
143
|
-
else
|
144
|
-
h[e[0].to_sym] = []
|
145
|
-
h[e[0].to_sym][e[1].to_i] = (e == path.last ? path.apply_filter(value) : {})
|
146
|
-
end
|
160
|
+
h[e] = (i == path.size-1 ? path.apply_filter(value) : {})
|
147
161
|
end
|
148
162
|
end
|
163
|
+
|
149
164
|
end
|
150
165
|
|
151
|
-
def contained?(h,e)
|
152
|
-
e[1].nil? ? h[e[0].to_sym] : h[e[0].to_sym][e[1].to_i].nil?
|
153
|
-
rescue
|
154
|
-
false
|
155
|
-
end
|
156
166
|
end
|
157
167
|
|
158
168
|
# contains array of path segments
|
@@ -177,21 +187,24 @@ module HashMapper
|
|
177
187
|
@segments.each(&blk)
|
178
188
|
end
|
179
189
|
|
190
|
+
def first
|
191
|
+
@segments.first
|
192
|
+
end
|
193
|
+
|
180
194
|
def last
|
181
195
|
@segments.last
|
182
196
|
end
|
183
197
|
|
198
|
+
def size
|
199
|
+
@segments.size
|
200
|
+
end
|
201
|
+
|
184
202
|
private
|
185
203
|
|
186
204
|
def parse(path)
|
187
|
-
|
188
|
-
path.sub(/^\//,'').split('/').map{ |p| key_index p }
|
189
|
-
end
|
190
|
-
|
191
|
-
def key_index(p)
|
192
|
-
p =~ /\[[0-9]+\]$/ ? p.sub(/\[([0-9]+)\]$/,' \1').split(' ') : [p,nil]
|
205
|
+
path.sub(/^\//,'').split('/').map(&:to_sym)
|
193
206
|
end
|
194
207
|
|
195
208
|
end
|
196
209
|
|
197
|
-
end
|
210
|
+
end
|
data/spec/hash_mapper_spec.rb
CHANGED
@@ -146,10 +146,12 @@ describe "array indexes" do
|
|
146
146
|
end
|
147
147
|
|
148
148
|
it "should extract defined array values" do
|
149
|
+
pending
|
149
150
|
WithArrays.normalize(@from).should == @to
|
150
151
|
end
|
151
152
|
|
152
153
|
it "should map the other way restoring arrays" do
|
154
|
+
pending
|
153
155
|
WithArrays.denormalize(@to).should == @from
|
154
156
|
end
|
155
157
|
end
|
@@ -283,8 +285,7 @@ describe "with non-matching maps" do
|
|
283
285
|
:doesnt_exist => 2
|
284
286
|
}
|
285
287
|
@output = {
|
286
|
-
:exists_yahoo => 1
|
287
|
-
:exists_nil => nil
|
288
|
+
:exists_yahoo => 1
|
288
289
|
}
|
289
290
|
end
|
290
291
|
|
@@ -296,14 +297,15 @@ end
|
|
296
297
|
class WithBeforeFilters
|
297
298
|
extend HashMapper
|
298
299
|
map from('/hello'), to('/goodbye')
|
300
|
+
map from('/extra'), to('/extra')
|
299
301
|
|
300
302
|
before_normalize do |input, output|
|
301
|
-
|
302
|
-
|
303
|
+
input[:extra] = "extra #{input[:hello]} innit"
|
304
|
+
input
|
303
305
|
end
|
304
306
|
before_denormalize do |input, output|
|
305
307
|
input[:goodbye] = 'changed'
|
306
|
-
|
308
|
+
input
|
307
309
|
end
|
308
310
|
end
|
309
311
|
|
@@ -327,7 +329,7 @@ describe "before and after filters" do
|
|
327
329
|
@norm = {:goodbye => 'seeya later!'}
|
328
330
|
end
|
329
331
|
it "should allow filtering before normalize" do
|
330
|
-
WithBeforeFilters.normalize(@denorm).should == {:goodbye => 'wassup?!', :
|
332
|
+
WithBeforeFilters.normalize(@denorm).should == {:goodbye => 'wassup?!', :extra => 'extra wassup?! innit'}
|
331
333
|
end
|
332
334
|
it "should allow filtering before denormalize" do
|
333
335
|
WithBeforeFilters.denormalize(@norm).should == {:hello => 'changed'}
|
@@ -339,4 +341,45 @@ describe "before and after filters" do
|
|
339
341
|
WithAfterFilters.denormalize(@norm).should == {}
|
340
342
|
end
|
341
343
|
|
344
|
+
end
|
345
|
+
|
346
|
+
class NotRelated
|
347
|
+
extend HashMapper
|
348
|
+
map from('/n'), to('/n/n')
|
349
|
+
end
|
350
|
+
|
351
|
+
class A
|
352
|
+
extend HashMapper
|
353
|
+
map from('/a'), to('/a/a')
|
354
|
+
end
|
355
|
+
|
356
|
+
class B < A
|
357
|
+
map from('/b'), to('/b/b')
|
358
|
+
end
|
359
|
+
|
360
|
+
class C < B
|
361
|
+
map from('/c'), to('/c/c')
|
362
|
+
end
|
363
|
+
|
364
|
+
describe "inherited mappers" do
|
365
|
+
before :all do
|
366
|
+
@from = {
|
367
|
+
:a => 'a',
|
368
|
+
:b => 'b',
|
369
|
+
:c => 'c'
|
370
|
+
}
|
371
|
+
@to_b ={
|
372
|
+
:a => {:a => 'a'},
|
373
|
+
:b => {:b => 'b'}
|
374
|
+
}
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
it "should inherit mappings" do
|
379
|
+
B.normalize(@from).should == @to_b
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should not affect other mappers" do
|
383
|
+
NotRelated.normalize('n' => 'nn').should == {:n => {:n => 'nn'}}
|
384
|
+
end
|
342
385
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newbamboo-hash_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ismael Celis
|
@@ -9,11 +9,12 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-16 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: newgem
|
17
|
+
type: :development
|
17
18
|
version_requirement:
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
19
20
|
requirements:
|
@@ -23,6 +24,7 @@ dependencies:
|
|
23
24
|
version:
|
24
25
|
- !ruby/object:Gem::Dependency
|
25
26
|
name: hoe
|
27
|
+
type: :development
|
26
28
|
version_requirement:
|
27
29
|
version_requirements: !ruby/object:Gem::Requirement
|
28
30
|
requirements:
|