hash_mapper 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -123,6 +123,15 @@ Just use the denormalize() method instead:
123
123
  This will work with your block filters and even nested mappers (see below).
124
124
 
125
125
  === Advanced usage
126
+ ==== Array access
127
+ You want:
128
+
129
+ {:names => ['Ismael', 'Celis']} converted to {:first_name => 'Ismael', :last_name => 'Celis'}
130
+
131
+ Do this:
132
+
133
+ map from('/names[0]'), to('/first_name')
134
+ map from('/names[1]'), to('/last_name')
126
135
  ==== Nested mappers
127
136
 
128
137
  You want to map nested structures delegating to different mappers:
@@ -209,15 +218,7 @@ Note also that 'output' is correct at the time of the filter, i.e. before_normal
209
218
  == REQUIREMENTS:
210
219
 
211
220
  == TODO:
212
- ==== Array access
213
- You want:
214
-
215
- {:names => ['Ismael', 'Celis']} converted to {:first_name => 'Ismael', :last_name => 'Celis'}
216
221
 
217
- Do this:
218
-
219
- map from('/names[0]'), to('/first_name')
220
- map from('/names[1]'), to('/last_name')
221
222
 
222
223
  ==== Optimizations
223
224
 
data/Rakefile CHANGED
@@ -1,28 +1,22 @@
1
- %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
- require File.dirname(__FILE__) + '/lib/hash_mapper'
3
-
4
- # Generate all the Rake tasks
5
- # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
- $hoe = Hoe.new('hash_mapper', HashMapper::VERSION) do |p|
7
- p.developer('Ismael Celis', 'ismaelct@gmail.com')
8
- p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
- p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
10
- p.rubyforge_name = p.name # TODO this is default value
11
- # p.extra_deps = [
12
- # ['activesupport','>= 2.0.2'],
13
- # ]
14
- p.extra_dev_deps = [
15
- ['newgem', ">= #{::Newgem::VERSION}"]
16
- ]
17
-
18
- p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
- path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
- p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
- p.rsync_args = '-av --delete --ignore-errors'
22
- end
23
-
24
- require 'newgem/tasks' # load /tasks/*.rake
25
- Dir['tasks/**/*.rake'].each { |t| load t }
26
-
27
- # TODO - want other tests/tasks run by default? Add them to the list
28
- task :default => [:spec]
1
+ require 'rubygems'
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.authors = ["Ismael Celis"]
19
+ end
20
+ rescue LoadError
21
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
22
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.9
@@ -0,0 +1,54 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{hash_mapper}
8
+ s.version = "0.0.9"
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{2009-10-29}
13
+ s.description = %q{Tiny module that allows you to easily adapt from one hash structure to another with a simple declarative DSL.}
14
+ s.email = %q{ismaelct@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ "History.txt",
20
+ "Manifest.txt",
21
+ "PostInstall.txt",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "hash_mapper.gemspec",
26
+ "lib/hash_mapper.rb",
27
+ "script/console",
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.5}
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::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
+ else
51
+ end
52
+ else
53
+ end
54
+ end
data/lib/hash_mapper.rb CHANGED
@@ -40,8 +40,7 @@ unless Array.instance_methods.include?("inject_with_index")
40
40
  end
41
41
 
42
42
  module HashMapper
43
- VERSION = '0.0.8'
44
-
43
+
45
44
  # we need this for inheritable mappers, which is annoying because it needs ActiveSupport, kinda overkill.
46
45
  #
47
46
  def self.extended(base)
@@ -50,24 +49,24 @@ module HashMapper
50
49
  class_inheritable_accessor :maps
51
50
  end
52
51
  end
53
-
52
+
54
53
  def map(from, to, using=nil, &filter)
55
54
  self.maps << Map.new(from, to, using)
56
55
  to.filter = filter if block_given? # Useful if just one block given
57
56
  end
58
-
57
+
59
58
  def from(path, &filter)
60
59
  path_map = PathMap.new(path)
61
60
  path_map.filter = filter if block_given? # Useful if two blocks given
62
61
  path_map
63
62
  end
64
-
63
+
65
64
  alias :to :from
66
-
65
+
67
66
  def using(mapper_class)
68
67
  mapper_class
69
68
  end
70
-
69
+
71
70
  def normalize(a_hash)
72
71
  perform_hash_mapping a_hash, :normalize
73
72
  end
@@ -75,7 +74,7 @@ module HashMapper
75
74
  def denormalize(a_hash)
76
75
  perform_hash_mapping a_hash, :denormalize
77
76
  end
78
-
77
+
79
78
  def before_normalize(&blk)
80
79
  @before_normalize = blk
81
80
  end
@@ -91,10 +90,10 @@ module HashMapper
91
90
  def after_denormalize(&blk)
92
91
  @after_denormalize = blk
93
92
  end
94
-
93
+
95
94
  protected
96
95
 
97
-
96
+
98
97
  def perform_hash_mapping(a_hash, meth)
99
98
  output = {}
100
99
  # Before filter
@@ -110,18 +109,18 @@ module HashMapper
110
109
  # Return
111
110
  output
112
111
  end
113
-
112
+
114
113
  # Contains PathMaps
115
114
  # Makes them interact
116
115
  #
117
116
  class Map
118
-
117
+
119
118
  attr_reader :path_from, :path_to, :delegated_mapper
120
-
119
+
121
120
  def initialize(path_from, path_to, delegated_mapper = nil)
122
121
  @path_from, @path_to, @delegated_mapper = path_from, path_to, delegated_mapper
123
122
  end
124
-
123
+
125
124
  def process_into(output, input, meth = :normalize)
126
125
  path_1, path_2 = (meth == :normalize ? [path_from, path_to] : [path_to, path_from])
127
126
  catch :no_value do
@@ -129,19 +128,22 @@ module HashMapper
129
128
  add_value_to_hash!(output, path_2, value)
130
129
  end
131
130
  end
132
-
133
131
  protected
134
-
132
+
135
133
  def get_value_from_input(output, input, path, meth)
136
134
  value = path.inject(input) do |h,e|
137
- v = h.with_indifferent_access[e] # this does it, but uses ActiveSupport
135
+ if h.respond_to?(:with_indifferent_access)# this does it, but uses ActiveSupport
136
+ v = h.with_indifferent_access[e]
137
+ else
138
+ v = h[e]
139
+ end
138
140
  throw :no_value if v.nil?#.has_key?(e)
139
141
  v
140
142
  end
141
143
  delegated_mapper ? delegate_to_nested_mapper(value, meth) : value
142
144
  end
143
-
144
-
145
+
146
+
145
147
  def delegate_to_nested_mapper(value, meth)
146
148
  case value
147
149
  when Array
@@ -152,60 +154,81 @@ module HashMapper
152
154
  delegated_mapper.send(meth, value)
153
155
  end
154
156
  end
155
-
157
+
156
158
  def add_value_to_hash!(hash, path, value)
157
159
  path.inject_with_index(hash) do |h,e,i|
158
160
  if !h[e].nil? # it can be FALSE
159
161
  h[e]
160
162
  else
161
- h[e] = (i == path.size-1 ? path.apply_filter(value) : {})
163
+ h[e] = if i == path.size-1
164
+ path.apply_filter(value)
165
+ else
166
+ if path.segments[i+1].is_a? Integer
167
+ []
168
+ else
169
+ {}
170
+ end
171
+ end
162
172
  end
163
173
  end
164
-
174
+
165
175
  end
166
-
176
+
167
177
  end
168
-
178
+
169
179
  # contains array of path segments
170
180
  #
171
181
  class PathMap
172
182
  include Enumerable
173
-
183
+
174
184
  attr_reader :segments
175
185
  attr_writer :filter
176
-
186
+ attr_reader :path
187
+
177
188
  def initialize(path)
178
189
  @path = path.dup
179
190
  @segments = parse(path)
180
191
  @filter = lambda{|value| value}# default filter does nothing
181
192
  end
182
-
193
+
183
194
  def apply_filter(value)
184
195
  @filter.call(value)
185
196
  end
186
-
197
+
187
198
  def each(&blk)
188
199
  @segments.each(&blk)
189
200
  end
190
-
201
+
191
202
  def first
192
203
  @segments.first
193
204
  end
194
-
205
+
195
206
  def last
196
207
  @segments.last
197
208
  end
198
-
209
+
199
210
  def size
200
211
  @segments.size
201
212
  end
202
-
213
+
203
214
  private
204
-
215
+ KEY_NAME_REGEXP = /([^\[]*)(\[(\d+)+\])?/
216
+
205
217
  def parse(path)
206
- path.sub(/^\//,'').split('/').map(&:to_sym)
218
+
219
+ segments = path.sub(/^\//,'').split('/')
220
+ segments = segments.collect do |segment|
221
+ matches = segment.to_s.scan(KEY_NAME_REGEXP).flatten.compact
222
+ index = matches[2]
223
+ if index
224
+ [matches[0].to_sym, index.to_i]
225
+ else
226
+ segment.to_sym
227
+ end
228
+ end.flatten
229
+ segments
207
230
  end
208
-
231
+
209
232
  end
210
-
233
+
211
234
  end
@@ -146,12 +146,10 @@ describe "array indexes" do
146
146
  end
147
147
 
148
148
  it "should extract defined array values" do
149
- pending
150
149
  WithArrays.normalize(@from).should == @to
151
150
  end
152
151
 
153
152
  it "should map the other way restoring arrays" do
154
- pending
155
153
  WithArrays.denormalize(@to).should == @from
156
154
  end
157
155
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hash_mapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Celis
@@ -9,43 +9,17 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-05 00:00:00 +01:00
12
+ date: 2009-10-29 00:00:00 +00:00
13
13
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: newgem
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 1.2.3
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: hoe
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.8.0
34
- version:
35
- description: |-
36
- 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).
37
-
38
- Tiny module that allows you to easily adapt from one hash structure to another with a simple declarative DSL.
39
- email:
40
- - ismaelct@gmail.com
14
+ dependencies: []
15
+
16
+ description: Tiny module that allows you to easily adapt from one hash structure to another with a simple declarative DSL.
17
+ email: ismaelct@gmail.com
41
18
  executables: []
42
19
 
43
20
  extensions: []
44
21
 
45
22
  extra_rdoc_files:
46
- - History.txt
47
- - Manifest.txt
48
- - PostInstall.txt
49
23
  - README.rdoc
50
24
  files:
51
25
  - History.txt
@@ -53,6 +27,8 @@ files:
53
27
  - PostInstall.txt
54
28
  - README.rdoc
55
29
  - Rakefile
30
+ - VERSION
31
+ - hash_mapper.gemspec
56
32
  - lib/hash_mapper.rb
57
33
  - script/console
58
34
  - script/destroy
@@ -65,10 +41,9 @@ has_rdoc: true
65
41
  homepage: http://github.com/ismasan/hash_mapper
66
42
  licenses: []
67
43
 
68
- post_install_message: PostInstall.txt
44
+ post_install_message:
69
45
  rdoc_options:
70
- - --main
71
- - README.rdoc
46
+ - --charset=UTF-8
72
47
  require_paths:
73
48
  - lib
74
49
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -85,10 +60,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
60
  version:
86
61
  requirements: []
87
62
 
88
- rubyforge_project: hash_mapper
63
+ rubyforge_project:
89
64
  rubygems_version: 1.3.5
90
65
  signing_key:
91
66
  specification_version: 3
92
- summary: Maps values from hashes with different structures and/or key names
93
- test_files: []
94
-
67
+ 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)
68
+ test_files:
69
+ - spec/hash_mapper_spec.rb
70
+ - spec/spec_helper.rb