Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
the ruby container you've always wanted: an ordered string/symbol indifferent hash
Ruby
Tree: 6440f7a371

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
test
.gitignore
LICENSE
README
Rakefile
map.gemspec

README

NAME
  map.rb

SYNOPSIS
  the awesome ruby container you've always wanted: a string/symbol indifferent
  ordered hash that works in all rubies

  maps are bitchin ordered hashes that are both ordered, string/symbol
  indifferent, and have all sorts of sweetness like recursive conversion, more
  robust implementation than HashWithIndifferentAccess, support for struct
  like (map.foo) access, and support for option/keyword access which avoids
  several nasty classes of errors in many ruby libraries

INSTALL
  gem install map

URI
  http://github.com/ahoward/map

DESCRIPTION

# maps are always ordered.  constructing them in an ordered fashion builds
# them that way, although the normal hash contructor is also supported
#
  m = Map[:k, :v, :key, :val]
  m = Map(:k, :v, :key, :val)
  m = Map.new(:k, :v, :key, :val)

  m = Map[[:k, :v], [:key, :val]]
  m = Map(:k => :v, :key => :val)  # ruh-oh, the input hash loses order!
  m = Map.new(:k => :v, :key => :val)  # ruh-oh, the input hash loses order!


  m = Map.new
  m[:a] = 0
  m[:b] = 1
  m[:c] = 2

  p m.keys #=> ['a','b','c']  ### always ordered!
  p m.keys #=> [0,1,2]        ### always ordered!

# maps don't care about symbol vs.string keys
#
  p m[:a]  #=> 0
  p m["a"] #=> 0

# even via deep nesting 
#
  p m[:foo]['bar'][:baz]  #=> 42

# many functions operate in a way one would expect from an ordered container
#
  m.update(:k2 => :v2)
  m.update(:k2, :v2)

  key_val_pair = m.shift
  key_val_pair = m.pop

# maps keep mapiness for even deep operations
#
  m.update :nested => {:hashes => {:are => :converted}}

# maps can give back clever little struct objects
#
  m = Map(:foo => {:bar => 42})
  s = m.struct
  p s.foo.bar #=> 42

# because option parsing is such a common use case for needing string/symbol
# indifference map.rb comes out of the box loaded with option support
#
  def foo(*args, &block)
    opts = Map.options(args)
    a = opts.getopt(:a)
    b = opts.getopt(:b, :default => false)
  end


  opts = Map.options(:a => 42, :b => nil, :c => false)
  opts.getopt(:a)                    #=> 42
  opts.getopt(:b)                    #=> nil
  opts.getopt(:b, :default => 42)    #=> 42 
  opts.getopt(:c)                    #=> false
  opts.getopt(:d, :default => false) #=> false

# this avoids such bugs as
#  
  options = {:read_only => false}
  read_only = options[:read_only] || true  # should be false but is true

# with options this becomes
#
  options = Map.options(:read_only => true)
  read_only = options.getopt(:read_only, :default => false) #=> true

# maps support some really nice operators that hashes/orderedhashes do not
#
  m = Map.new
  m.set(:h, :a, 0, 42)
  m.has?(:h, :a)         #=> true
  p m                    #=> {'h' => {'a' => [42]}} 
  m.set(:h, :a, 1, 42.0)
  p m                    #=> {'h' => {'a' => [42, 42.0]}} 

  m.get(:h, :a, 1)       #=> 42.0
  m.get(:x, :y, :z)      #=> nil
  m[:x][:y][:z]          #=> raises exception!

  m = Map.new(:array => [0,1])
  defaults = {:array => [nil, nil, 2]}
  m.apply!(defaults)
  p m[:array]            #=> [0,1,2]

# they also support some different iteration styles
#
  m = Map.new

  m.set(
    [:a, :b, :c, 0] => 0,
    [:a, :b, :c, 1] => 10,
    [:a, :b, :c, 2] => 20,
    [:a, :b, :c, 3] => 30
  )

  m.set(:x, :y, 42)
  m.set(:x, :z, 42.0)

  m.depth_first_each do |key, val|
    p key => val
  end

  #=> [:a, :b, :c, 0] => 0
  #=> [:a, :b, :c, 1] => 10
  #=> [:a, :b, :c, 2] => 20
  #=> [:a, :b, :c, 3] => 30
  #=> [:x, :y] => 42
  #=> [:x, :z] => 42.0


USAGE
  see lib/map.rb and test/map_test.rb

HISTORY
  4.3.0:
    - support for dot keys. map.set('a.b.c' => 42) #=> {'a'=>{'b'=>{'c'=>42}}}
Something went wrong with that request. Please try again.