lib/hash_mapper.rb in ismasan-hash_mapper-0.0.5 vs lib/hash_mapper.rb in ismasan-hash_mapper-0.0.6
- old
+ new
@@ -1,22 +1,46 @@
$:.unshift(File.dirname(__FILE__)) unless
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
+begin
+ require 'active_support'
+rescue LoadError
+ require 'rubygems'
+ require 'active_support'
+end
+
+
+
# This allows us to call blah(&:some_method) instead of blah{|i| i.some_method }
unless Symbol.instance_methods.include?('to_proc')
class Symbol
def to_proc
Proc.new {|obj| obj.send(self) }
end
end
end
+# http://rpheath.com/posts/341-ruby-inject-with-index
+unless Array.instance_methods.include?("inject_with_index")
+ module Enumerable
+ def inject_with_index(injected)
+ each_with_index{ |obj, index| injected = yield(injected, obj, index) }
+ injected
+ end
+ end
+end
+
module HashMapper
- VERSION = '0.0.5'
+ VERSION = '0.0.6'
- def maps
- @maps ||= []
+ # we need this for inheritable mappers, which is annoying because it needs ActiveSupport, kinda overkill.
+ #
+ def self.extended(base)
+ base.class_eval do
+ write_inheritable_attribute :maps, []
+ class_inheritable_accessor :maps
+ end
end
def map(from, to, using=nil, &filter)
self.maps << Map.new(from, to, using)
to.filter = filter if block_given? # Useful if just one block given
@@ -39,19 +63,44 @@
end
def denormalize(a_hash)
perform_hash_mapping a_hash, :denormalize
end
+
+ def before_normalize(&blk)
+ @before_normalize = blk
+ end
+ def before_denormalize(&blk)
+ @before_denormalize = blk
+ end
+
+ def after_normalize(&blk)
+ @after_normalize = blk
+ end
+
+ def after_denormalize(&blk)
+ @after_denormalize = blk
+ end
+
protected
+
def perform_hash_mapping(a_hash, meth)
output = {}
+ # Before filter
+ before_filter = instance_eval "@before_#{meth}"
+ a_hash = before_filter.call(a_hash, output) if before_filter
+ # Do the mapping
a_hash = symbolize_keys(a_hash)
maps.each do |m|
m.process_into(output, a_hash, meth)
end
+ # After filter
+ after_filter = instance_eval "@after_#{meth}"
+ output = after_filter.call(a_hash, output) if after_filter
+ # Return
output
end
# from http://www.geekmade.co.uk/2008/09/ruby-tip-normalizing-hash-keys-as-symbols/
#
@@ -83,54 +132,39 @@
protected
def get_value_from_input(output, input, path, meth)
value = path.inject(input) do |h,e|
- throw :no_value unless h.has_key?(e[0].to_sym)
- e[1].nil? ? h[e[0].to_sym] : h[e[0].to_sym][e[1].to_i]
- #h[e[0].to_sym]
+ throw :no_value if h[e].nil?#.has_key?(e)
+ h[e]
end
- value = delegate_to_nested_mapper(value, meth) if delegated_mapper
- value
+ delegated_mapper ? delegate_to_nested_mapper(value, meth) : value
end
def delegate_to_nested_mapper(value, meth)
- v = if value.kind_of?(Array)
+ case value
+ when Array
value.map {|h| delegated_mapper.send(meth, h)}
+ when nil
+ throw :no_value
else
delegated_mapper.send(meth, value)
end
end
def add_value_to_hash!(hash, path, value)
- path.inject(hash) do |h,e|
- if contained?(h,e)
- if e[1].nil?
- h[e[0].to_sym]
- else
- if e == path.last
- h[e[0].to_sym][e[1].to_i] = value
- end
- h[e[0].to_sym][e[1].to_i]
- end
+ path.inject_with_index(hash) do |h,e,i|
+ if h[e]
+ h[e]
else
- if e[1].nil?
- h[e[0].to_sym] = (e == path.last ? path.apply_filter(value) : {})
- else
- h[e[0].to_sym] = []
- h[e[0].to_sym][e[1].to_i] = (e == path.last ? path.apply_filter(value) : {})
- end
+ h[e] = (i == path.size-1 ? path.apply_filter(value) : {})
end
end
+
end
- def contained?(h,e)
- e[1].nil? ? h[e[0].to_sym] : h[e[0].to_sym][e[1].to_i].nil?
- rescue
- false
- end
end
# contains array of path segments
#
class PathMap
@@ -151,23 +185,26 @@
def each(&blk)
@segments.each(&blk)
end
+ def first
+ @segments.first
+ end
+
def last
@segments.last
end
+ def size
+ @segments.size
+ end
+
private
def parse(path)
- #path.sub(/^\//,'').split('/').map(&:to_sym)
- path.sub(/^\//,'').split('/').map{ |p| key_index p }
+ path.sub(/^\//,'').split('/').map(&:to_sym)
end
- def key_index(p)
- p =~ /\[[0-9]+\]$/ ? p.sub(/\[([0-9]+)\]$/,' \1').split(' ') : [p,nil]
- end
-
end
-end
\ No newline at end of file
+end