hash_mapper 0.0.8 → 0.0.9

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 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