hash_mapper 0.0.10 → 0.1.1
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/.gitignore +6 -0
- data/Gemfile +4 -0
- data/History.txt +6 -0
- data/{README.rdoc → README.md} +174 -124
- data/Rakefile +1 -23
- data/hash_mapper.gemspec +24 -51
- data/lib/hash_mapper/version.rb +3 -0
- data/lib/hash_mapper.rb +10 -10
- data/spec/hash_mapper_spec.rb +2 -2
- data/spec/spec_helper.rb +10 -6
- metadata +36 -38
- data/Manifest.txt +0 -13
- data/PostInstall.txt +0 -7
- data/VERSION +0 -1
- data/script/console +0 -10
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/spec/spec.opts +0 -1
- data/tasks/rspec.rake +0 -21
data/.gitignore
ADDED
data/Gemfile
ADDED
data/History.txt
CHANGED
data/{README.rdoc → README.md}
RENAMED
@@ -1,192 +1,241 @@
|
|
1
|
-
|
1
|
+
# hash_mapper
|
2
2
|
|
3
|
-
* http://github.com/
|
3
|
+
* http://ismasan.github.com/hash_mapper/
|
4
4
|
|
5
|
-
|
5
|
+
## DESCRIPTION:
|
6
6
|
|
7
7
|
Maps values from hashes with different structures and/or key names. Ideal for normalizing arbitrary data to be consumed by your applications, or to prepare your data for different display formats (ie. json).
|
8
8
|
|
9
9
|
Tiny module that allows you to easily adapt from one hash structure to another with a simple declarative DSL.
|
10
10
|
|
11
|
-
|
11
|
+
## FEATURES/PROBLEMS:
|
12
12
|
|
13
13
|
It is a module so it doesn't get in the way of your inheritance tree.
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
15
|
+
## SYNOPSIS:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
class ManyLevels
|
19
|
+
extend HashMapper
|
20
|
+
map from('/name'), to('/tag_attributes/name')
|
21
|
+
map from('/properties/type'), to('/tag_attributes/type')
|
22
|
+
map from('/tagid'), to('/tag_id')
|
23
|
+
map from('/properties/egg'), to('/chicken')
|
24
|
+
end
|
25
|
+
|
26
|
+
input = {
|
27
|
+
:name => 'ismael',
|
28
|
+
:tagid => 1,
|
29
|
+
:properties => {
|
30
|
+
:type => 'BLAH',
|
31
|
+
:egg => 33
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
ManyLevels.normalize(input)
|
36
|
+
|
37
|
+
# outputs:
|
38
|
+
{
|
39
|
+
:tag_id => 1,
|
40
|
+
:chicken => 33,
|
41
|
+
:tag_attributes => {
|
42
|
+
:name => 'ismael',
|
43
|
+
:type => 'BLAH'
|
44
|
+
}
|
45
|
+
}
|
46
|
+
```
|
47
|
+
|
48
|
+
### Uses:
|
47
49
|
|
48
50
|
HashMapper was primarily written as a way of mapping data structure in json requests to hashes with structures friendlier to our ActiveRecord models:
|
49
51
|
|
50
|
-
|
52
|
+
```ruby
|
53
|
+
@article = Article.create( ArticleParams.normalize(params[:weird_article_data]) )
|
54
|
+
```
|
51
55
|
|
52
56
|
You can use HashMapper in your own little hash-like objects:
|
53
57
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
```ruby
|
59
|
+
class NiceHash
|
60
|
+
include Enumerable
|
61
|
+
extend HashMapper
|
62
|
+
|
63
|
+
map from('/names/first'), to('/first_name')
|
64
|
+
map from('/names/last'), to('/last_name')
|
60
65
|
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
def initialize(input_hash)
|
67
|
+
@hash = self.class.normalize(input_hash)
|
68
|
+
end
|
64
69
|
|
65
|
-
|
66
|
-
|
67
|
-
|
70
|
+
def [](k)
|
71
|
+
@hash[k]
|
72
|
+
end
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
74
|
+
def []=(k,v)
|
75
|
+
@hash[k] = v
|
76
|
+
end
|
72
77
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
78
|
+
def each(&block)
|
79
|
+
@hash.each(&block)
|
80
|
+
end
|
81
|
+
end
|
77
82
|
|
78
|
-
|
83
|
+
@user = User.new(NiceHash.new(params))
|
84
|
+
```
|
79
85
|
|
80
|
-
|
86
|
+
### Options:
|
81
87
|
|
82
|
-
|
88
|
+
#### Coercing values
|
83
89
|
|
84
90
|
You want to make sure an incoming value gets converted to a certain type, so
|
85
91
|
|
86
|
-
|
92
|
+
```ruby
|
93
|
+
{'one' => '1', 'two' => '2'}
|
94
|
+
```
|
95
|
+
|
96
|
+
gets translated to
|
97
|
+
|
98
|
+
```ruby`
|
99
|
+
{:one => 1, :two => 2}
|
100
|
+
```
|
87
101
|
|
88
102
|
Do this:
|
89
103
|
|
90
|
-
|
91
|
-
|
104
|
+
```ruby
|
105
|
+
map from('/one'), to('/one', &:to_i)
|
106
|
+
map from('/two'), to('/two', &:to_i)
|
107
|
+
```
|
92
108
|
|
93
109
|
You can pass :to_i, :to_s or anything available method that makes sense. Don't forget the block notation (&).
|
94
110
|
|
95
111
|
You guessed it. That means that you can actually pass custom blocks to each to() definition as well. The following is similar to the previous example:
|
96
112
|
|
97
|
-
|
113
|
+
```ruby
|
114
|
+
map from('/one), to('/one'){|value| value.to_i}
|
115
|
+
```
|
98
116
|
|
99
|
-
|
117
|
+
#### Custom value filtering
|
100
118
|
|
101
119
|
You want to pass the final value of a key through a custom filter:
|
102
120
|
|
121
|
+
```ruby
|
103
122
|
{:names => {:first => 'Ismael', :last => 'Celis'}} gets translated to {:user => 'Mr. Celis, Ismael'}
|
123
|
+
```
|
104
124
|
|
105
125
|
Do this:
|
106
126
|
|
107
|
-
|
108
|
-
|
109
|
-
|
127
|
+
```ruby
|
128
|
+
map from('/names'), to('/user') do |names|
|
129
|
+
"Mr. #{names[1]}, #{names[0]}"
|
130
|
+
end
|
131
|
+
```
|
110
132
|
|
111
|
-
|
133
|
+
### Mapping in reverse
|
112
134
|
|
113
135
|
Cool, you can map one hash into another, but what if I want the opposite operation?
|
114
136
|
|
115
137
|
Just use the denormalize() method instead:
|
116
138
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
139
|
+
```ruby
|
140
|
+
input = {:first => 'Mark', :last => 'Evans'}
|
141
|
+
|
142
|
+
output = NameMapper.normalize(input) # => {:first_name => 'Mark', :last_name => 'Evans'}
|
143
|
+
|
144
|
+
NameMapper.denormalize(output) # => input
|
145
|
+
```
|
122
146
|
|
123
147
|
This will work with your block filters and even nested mappers (see below).
|
124
148
|
|
125
|
-
|
126
|
-
|
149
|
+
### Advanced usage
|
150
|
+
#### Array access
|
127
151
|
You want:
|
128
152
|
|
129
|
-
|
153
|
+
```ruby
|
154
|
+
{:names => ['Ismael', 'Celis']}
|
155
|
+
```
|
156
|
+
|
157
|
+
converted to
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
{:first_name => 'Ismael', :last_name => 'Celis'}
|
161
|
+
```
|
130
162
|
|
131
163
|
Do this:
|
132
164
|
|
133
|
-
|
134
|
-
|
135
|
-
|
165
|
+
```ruby
|
166
|
+
map from('/names[0]'), to('/first_name')
|
167
|
+
map from('/names[1]'), to('/last_name')
|
168
|
+
```
|
169
|
+
|
170
|
+
#### Nested mappers
|
136
171
|
|
137
172
|
You want to map nested structures delegating to different mappers:
|
138
173
|
|
139
174
|
From this:
|
175
|
+
|
176
|
+
```ruby
|
140
177
|
input = {
|
141
178
|
:project => 'HashMapper',
|
142
179
|
:url => 'http://github.com/ismasan/hash_mapper',
|
143
180
|
:author_names => {:first => 'Ismael', :last => 'Celis'}
|
144
181
|
}
|
182
|
+
```
|
183
|
+
|
145
184
|
To this:
|
185
|
+
|
186
|
+
```ruby
|
146
187
|
output = {
|
147
188
|
:project_name => 'HashMapper',
|
148
189
|
:url => 'http://github.com/ismasan/hash_mapper',
|
149
190
|
:author => {:first_name => 'Ismael', :last_name => 'Celis'}
|
150
191
|
}
|
192
|
+
```
|
151
193
|
|
152
194
|
Define an UserMapper separate from your ProjectMapper, so you reuse them combined or standalone
|
153
195
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
196
|
+
```ruby
|
197
|
+
class UserMapper
|
198
|
+
extend HashMapper
|
199
|
+
map from('/first'), to('/first_name')
|
200
|
+
map from('/last'), to('/lastt_name')
|
201
|
+
end
|
202
|
+
|
203
|
+
class ProjectMapper
|
204
|
+
extend HashMapper
|
205
|
+
map from('/project'), to('/project_name')
|
206
|
+
map from('/url'), to('/url')
|
207
|
+
map from('/author_names'), to('/author'), using(UserMapper)
|
208
|
+
end
|
209
|
+
```
|
166
210
|
|
167
211
|
Now ProjectMapper will delegate parsing of :author_names to UserMapper
|
168
212
|
|
169
|
-
|
213
|
+
```ruby
|
214
|
+
ProjectMapper.normalize( input ) # => output
|
215
|
+
```
|
170
216
|
|
171
217
|
Let's say you have a CompanyMapper which maps a hash with an array of employees, and you want to reuse UserMapper to map each employee. You could:
|
172
218
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
219
|
+
```ruby
|
220
|
+
class CompanyMapper
|
221
|
+
map from('/info/name'), to('/company_name')
|
222
|
+
map form('/info/address'), to('/company_address')
|
223
|
+
map from('/info/year_founded'), to('year_founded', :to_i)
|
177
224
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
225
|
+
map from('/employees'), to('employees') do |employees_array|
|
226
|
+
employees_array.collect {|emp_hash| UserMapper.normalize(emp_hash)}
|
227
|
+
end
|
228
|
+
end
|
229
|
+
```
|
182
230
|
|
183
231
|
But HashMapper's nested mappers will actually do that for you if a value is an array, so:
|
184
|
-
|
185
|
-
|
186
|
-
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
map from('/employees'), to('employees'), using(UserMapper)
|
235
|
+
```
|
187
236
|
... Will map each employee using UserMapper.
|
188
237
|
|
189
|
-
|
238
|
+
#### Before and after filters
|
190
239
|
|
191
240
|
Sometimes you will need some slightly more complex processing on the whole hash, either before or after normalizing/denormalizing.
|
192
241
|
|
@@ -194,40 +243,41 @@ For this you can use the class methods before_normalize, before_denormalize, aft
|
|
194
243
|
|
195
244
|
They all yield a block with 2 arguments - the hash you are mapping from and the hash you are mapping to, e.g.
|
196
245
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
246
|
+
```ruby
|
247
|
+
class EggMapper
|
248
|
+
map from('/raw'), to('/fried')
|
249
|
+
|
250
|
+
before_normalize do |input, output|
|
251
|
+
input['raw'] ||= 'please' # this will give 'raw' a default value
|
252
|
+
input
|
253
|
+
end
|
254
|
+
|
255
|
+
after_denormalize do |input, output|
|
256
|
+
output.to_a # the denormalized object will now be an array, not a hash!!
|
209
257
|
end
|
210
258
|
|
259
|
+
end
|
260
|
+
```
|
261
|
+
|
211
262
|
Important: note that for before filters, you need to return the (modified) input, and for after filters, you need to return the output.
|
212
263
|
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.
|
213
264
|
|
214
265
|
|
215
|
-
|
266
|
+
## REQUIREMENTS:
|
216
267
|
|
217
|
-
|
268
|
+
## TODO:
|
218
269
|
|
219
270
|
|
220
|
-
|
271
|
+
#### Optimizations
|
221
272
|
|
222
273
|
* Get rid of ActiveSupport (used for inherited class variables and HashWithIndifferentAccess)
|
223
274
|
|
224
|
-
|
275
|
+
## INSTALL:
|
225
276
|
|
226
|
-
# Now install
|
227
277
|
|
228
|
-
|
278
|
+
gem install hash_mapper
|
229
279
|
|
230
|
-
|
280
|
+
## Credits:
|
231
281
|
|
232
282
|
* Ismael Celis (Author - http://www.estadobeta.com)
|
233
283
|
* Mark Evans (Contributor - http://github.com/markevans)
|
@@ -235,7 +285,7 @@ Note also that 'output' is correct at the time of the filter, i.e. before_normal
|
|
235
285
|
* nightscape (Contributor - http://github.com/nightscape)
|
236
286
|
* radamanthus (Contributor - http://github.com/radamanthus)
|
237
287
|
|
238
|
-
|
288
|
+
## LICENSE:
|
239
289
|
|
240
290
|
(The MIT License)
|
241
291
|
|
data/Rakefile
CHANGED
@@ -1,23 +1 @@
|
|
1
|
-
require
|
2
|
-
require File.dirname(__FILE__) + '/lib/hash_mapper'
|
3
|
-
|
4
|
-
Dir['tasks/**/*.rake'].each { |t| load t }
|
5
|
-
|
6
|
-
# TODO - want other tests/tasks run by default? Add them to the list
|
7
|
-
task :default => [:spec]
|
8
|
-
|
9
|
-
|
10
|
-
begin
|
11
|
-
require 'jeweler'
|
12
|
-
Jeweler::Tasks.new do |gemspec|
|
13
|
-
gemspec.name = "hash_mapper"
|
14
|
-
gemspec.summary = "Maps values from hashes with different structures and/or key names. Ideal for normalizing arbitrary data to be consumed by your applications, or to prepare your data for different display formats (ie. json)"
|
15
|
-
gemspec.description = "Tiny module that allows you to easily adapt from one hash structure to another with a simple declarative DSL."
|
16
|
-
gemspec.email = "ismaelct@gmail.com"
|
17
|
-
gemspec.homepage = "http://github.com/ismasan/hash_mapper"
|
18
|
-
gemspec.add_dependency('active_support', '>= 3.0.0.beta')
|
19
|
-
gemspec.authors = ["Ismael Celis"]
|
20
|
-
end
|
21
|
-
rescue LoadError
|
22
|
-
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
23
|
-
end
|
1
|
+
require "bundler/gem_tasks"
|
data/hash_mapper.gemspec
CHANGED
@@ -1,58 +1,31 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'hash_mapper/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
9
|
-
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Ismael Celis"]
|
12
|
-
s.date = %q{2010-09-21}
|
6
|
+
s.name = %q{hash_mapper}
|
7
|
+
s.version = HashMapper::VERSION
|
8
|
+
s.authors = ['Ismael Celis']
|
13
9
|
s.description = %q{Tiny module that allows you to easily adapt from one hash structure to another with a simple declarative DSL.}
|
14
|
-
s.
|
15
|
-
s.
|
16
|
-
|
17
|
-
|
18
|
-
s.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
"script/destroy",
|
29
|
-
"script/generate",
|
30
|
-
"spec/hash_mapper_spec.rb",
|
31
|
-
"spec/spec.opts",
|
32
|
-
"spec/spec_helper.rb",
|
33
|
-
"tasks/rspec.rake"
|
34
|
-
]
|
35
|
-
s.homepage = %q{http://github.com/ismasan/hash_mapper}
|
36
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
37
|
-
s.require_paths = ["lib"]
|
38
|
-
s.rubygems_version = %q{1.3.7}
|
39
|
-
s.summary = %q{Maps values from hashes with different structures and/or key names. Ideal for normalizing arbitrary data to be consumed by your applications, or to prepare your data for different display formats (ie. json)}
|
40
|
-
s.test_files = [
|
41
|
-
"spec/hash_mapper_spec.rb",
|
42
|
-
"spec/spec_helper.rb"
|
43
|
-
]
|
44
|
-
|
45
|
-
if s.respond_to? :specification_version then
|
46
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
47
|
-
s.specification_version = 3
|
48
|
-
|
49
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
50
|
-
s.add_runtime_dependency(%q<active_support>, [">= 3.0.0.beta"])
|
51
|
-
else
|
52
|
-
s.add_dependency(%q<active_support>, [">= 3.0.0.beta"])
|
53
|
-
end
|
10
|
+
s.date = %q{2010-09-21}
|
11
|
+
s.email = %q{ismaelct@gmail.com}
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.homepage = %q{http://github.com/ismasan/hash_mapper}
|
15
|
+
s.rdoc_options = ['--charset=UTF-8']
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
s.summary = %q{Maps input hashes to a normalized format}
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ['lib']
|
21
|
+
|
22
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
23
|
+
s.add_runtime_dependency("activesupport", "~> 3")
|
54
24
|
else
|
55
|
-
s.add_dependency(
|
25
|
+
s.add_dependency("activesupport", "~> 3")
|
56
26
|
end
|
27
|
+
|
28
|
+
# specify any dependencies here; for example:
|
29
|
+
s.add_development_dependency 'rspec'
|
30
|
+
s.add_development_dependency 'rake'
|
57
31
|
end
|
58
|
-
|
data/lib/hash_mapper.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
require 'hash_mapper/version'
|
2
|
+
|
1
3
|
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
-
|
4
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
5
|
|
4
6
|
def require_active_support
|
5
7
|
require 'active_support/core_ext/array/extract_options'
|
6
8
|
require 'active_support/core_ext/hash/indifferent_access'
|
7
9
|
require 'active_support/core_ext/object/duplicable'
|
8
|
-
require 'active_support/core_ext/class/
|
10
|
+
require 'active_support/core_ext/class/attribute'
|
9
11
|
end
|
10
12
|
|
11
13
|
begin
|
@@ -18,7 +20,7 @@ end
|
|
18
20
|
|
19
21
|
|
20
22
|
# This allows us to call blah(&:some_method) instead of blah{|i| i.some_method }
|
21
|
-
unless
|
23
|
+
unless :symbol.respond_to?(:to_proc)
|
22
24
|
class Symbol
|
23
25
|
def to_proc
|
24
26
|
Proc.new {|obj| obj.send(self) }
|
@@ -27,7 +29,7 @@ unless Symbol.instance_methods.include?('to_proc')
|
|
27
29
|
end
|
28
30
|
|
29
31
|
# http://rpheath.com/posts/341-ruby-inject-with-index
|
30
|
-
unless
|
32
|
+
unless [].respond_to?(:inject_with_index)
|
31
33
|
module Enumerable
|
32
34
|
def inject_with_index(injected)
|
33
35
|
each_with_index{ |obj, index| injected = yield(injected, obj, index) }
|
@@ -38,16 +40,15 @@ end
|
|
38
40
|
|
39
41
|
module HashMapper
|
40
42
|
|
41
|
-
# we need this for inheritable mappers, which is annoying because it needs ActiveSupport, kinda overkill.
|
42
|
-
#
|
43
43
|
def self.extended(base)
|
44
44
|
base.class_eval do
|
45
|
-
|
46
|
-
|
45
|
+
class_attribute :maps
|
46
|
+
self.maps = []
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
def map(from, to, using=nil, &filter)
|
51
|
+
self.maps = self.maps.dup
|
51
52
|
self.maps << Map.new(from, to, using)
|
52
53
|
to.filter = filter if block_given? # Useful if just one block given
|
53
54
|
end
|
@@ -97,7 +98,7 @@ module HashMapper
|
|
97
98
|
before_filter = instance_eval "@before_#{meth}"
|
98
99
|
a_hash = before_filter.call(a_hash, output) if before_filter
|
99
100
|
# Do the mapping
|
100
|
-
maps.each do |m|
|
101
|
+
self.maps.each do |m|
|
101
102
|
m.process_into(output, a_hash, meth)
|
102
103
|
end
|
103
104
|
# After filter
|
@@ -210,7 +211,6 @@ module HashMapper
|
|
210
211
|
KEY_NAME_REGEXP = /([^\[]*)(\[(\d+)+\])?/
|
211
212
|
|
212
213
|
def parse(path)
|
213
|
-
|
214
214
|
segments = path.sub(/^\//,'').split('/')
|
215
215
|
segments = segments.collect do |segment|
|
216
216
|
matches = segment.to_s.scan(KEY_NAME_REGEXP).flatten.compact
|
data/spec/hash_mapper_spec.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper.rb'
|
2
2
|
|
3
3
|
class OneLevel
|
4
4
|
extend HashMapper
|
5
5
|
map from('/name'), to('/nombre')
|
6
6
|
end
|
7
7
|
|
8
|
-
describe 'mapping a hash
|
8
|
+
describe 'mapping a hash with one level' do
|
9
9
|
|
10
10
|
before :each do
|
11
11
|
@from = {:name => 'ismael'}
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper.rb"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
7
11
|
end
|
8
12
|
|
9
13
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hash_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 10
|
10
|
-
version: 0.0.10
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.1
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Ismael Celis
|
@@ -15,51 +10,60 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2010-09-21 00:00:00
|
19
|
-
default_executable:
|
13
|
+
date: 2010-09-21 00:00:00 Z
|
20
14
|
dependencies:
|
21
15
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
16
|
+
name: activesupport
|
23
17
|
prerelease: false
|
24
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
19
|
none: false
|
26
20
|
requirements:
|
27
|
-
- -
|
21
|
+
- - ~>
|
28
22
|
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 3
|
32
|
-
- 0
|
33
|
-
- 0
|
34
|
-
- beta
|
35
|
-
version: 3.0.0.beta
|
23
|
+
version: "3"
|
36
24
|
type: :runtime
|
37
25
|
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rspec
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rake
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
38
48
|
description: Tiny module that allows you to easily adapt from one hash structure to another with a simple declarative DSL.
|
39
49
|
email: ismaelct@gmail.com
|
40
50
|
executables: []
|
41
51
|
|
42
52
|
extensions: []
|
43
53
|
|
44
|
-
extra_rdoc_files:
|
45
|
-
|
54
|
+
extra_rdoc_files: []
|
55
|
+
|
46
56
|
files:
|
57
|
+
- .gitignore
|
58
|
+
- Gemfile
|
47
59
|
- History.txt
|
48
|
-
-
|
49
|
-
- PostInstall.txt
|
50
|
-
- README.rdoc
|
60
|
+
- README.md
|
51
61
|
- Rakefile
|
52
|
-
- VERSION
|
53
62
|
- hash_mapper.gemspec
|
54
63
|
- lib/hash_mapper.rb
|
55
|
-
-
|
56
|
-
- script/destroy
|
57
|
-
- script/generate
|
64
|
+
- lib/hash_mapper/version.rb
|
58
65
|
- spec/hash_mapper_spec.rb
|
59
|
-
- spec/spec.opts
|
60
66
|
- spec/spec_helper.rb
|
61
|
-
- tasks/rspec.rake
|
62
|
-
has_rdoc: true
|
63
67
|
homepage: http://github.com/ismasan/hash_mapper
|
64
68
|
licenses: []
|
65
69
|
|
@@ -73,26 +77,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
77
|
requirements:
|
74
78
|
- - ">="
|
75
79
|
- !ruby/object:Gem::Version
|
76
|
-
hash: 3
|
77
|
-
segments:
|
78
|
-
- 0
|
79
80
|
version: "0"
|
80
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
82
|
none: false
|
82
83
|
requirements:
|
83
84
|
- - ">="
|
84
85
|
- !ruby/object:Gem::Version
|
85
|
-
hash: 3
|
86
|
-
segments:
|
87
|
-
- 0
|
88
86
|
version: "0"
|
89
87
|
requirements: []
|
90
88
|
|
91
89
|
rubyforge_project:
|
92
|
-
rubygems_version: 1.
|
90
|
+
rubygems_version: 1.8.17
|
93
91
|
signing_key:
|
94
92
|
specification_version: 3
|
95
|
-
summary: Maps
|
93
|
+
summary: Maps input hashes to a normalized format
|
96
94
|
test_files:
|
97
95
|
- spec/hash_mapper_spec.rb
|
98
96
|
- spec/spec_helper.rb
|
data/Manifest.txt
DELETED
data/PostInstall.txt
DELETED
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.0.10
|
data/script/console
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# File: script/console
|
3
|
-
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
-
|
5
|
-
libs = " -r irb/completion"
|
6
|
-
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
-
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
-
libs << " -r #{File.dirname(__FILE__) + '/../lib/hash_mapper.rb'}"
|
9
|
-
puts "Loading hash_mapper gem"
|
10
|
-
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'rubigen'
|
6
|
-
rescue LoadError
|
7
|
-
require 'rubygems'
|
8
|
-
require 'rubigen'
|
9
|
-
end
|
10
|
-
require 'rubigen/scripts/destroy'
|
11
|
-
|
12
|
-
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
-
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
-
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'rubigen'
|
6
|
-
rescue LoadError
|
7
|
-
require 'rubygems'
|
8
|
-
require 'rubigen'
|
9
|
-
end
|
10
|
-
require 'rubigen/scripts/generate'
|
11
|
-
|
12
|
-
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
-
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
-
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/spec/spec.opts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--colour
|
data/tasks/rspec.rake
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'spec'
|
3
|
-
rescue LoadError
|
4
|
-
require 'rubygems'
|
5
|
-
require 'spec'
|
6
|
-
end
|
7
|
-
begin
|
8
|
-
require 'spec/rake/spectask'
|
9
|
-
rescue LoadError
|
10
|
-
puts <<-EOS
|
11
|
-
To use rspec for testing you must install rspec gem:
|
12
|
-
gem install rspec
|
13
|
-
EOS
|
14
|
-
exit(0)
|
15
|
-
end
|
16
|
-
|
17
|
-
desc "Run the specs under spec/models"
|
18
|
-
Spec::Rake::SpecTask.new do |t|
|
19
|
-
t.spec_opts = ['--options', "spec/spec.opts"]
|
20
|
-
t.spec_files = FileList['spec/**/*_spec.rb']
|
21
|
-
end
|