Code Monkey home page Code Monkey logo

map's Introduction

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.values #=> [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}}}

map's People

Contributors

ahoward avatar bhb avatar cookrn avatar copiousfreetime avatar kohgpat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

map's Issues

Problem with #reject

Output from 'irb':

require 'map' #=> true
m = Map[1, Map[2, 3]] #=> {1=>{2=>3}}
m.reject { |a, b| p [a, b] } #=> {1=>{2=>3}}
[1, nil]
If value is map, then reject sees it as nil. Other methods seems to work fine (#each, #select).

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

a convenient way to serialize the order to JSON

Great library! I've been thinking I want ordered hashes in JavaScript, and I think having a key containing the order would be preferable to using an array of single key objects instead. That is, I think for most cases, {"a": 1, "b": 2, "_order": ["b", "a"]} would be more useful to me than [{"b": 2}, {"a": 1}]. With the former, I can address a key like obj.a. It also has fewer objects.

I made a first pass in my serialize_order branch. If it doesn't conflict with anything, I think it might be a good convenience method. It wouldn't work for serializing a complex data structure, though. I think overriding to_json might be the way to do that, but I'm not sure how to have options without making them global.

test fails due a Bang!

Hi...

Great code, great gem!
^_^

But running the test I've found a test that fail due a bang:

eddie@white:~/Coding/map$ ruby test/map_test.rb 
Loaded suite test/map_test
Started
................E
===============================================================================
Error: test_00016_simple-struct-usage(TESTING_001_MAP)
  IndexError: !
/home/eddie/Coding/map/lib/map/struct.rb:27:in `method_missing'
/home/eddie/Coding/map/test/lib/testing.rb:47:in `assert'
test/map_test.rb:178:in `block (2 levels) in <main>'
===============================================================================
E
===============================================================================
Error: test_00017_nested-struct-usage(TESTING_001_MAP)
  IndexError: !
/home/eddie/Coding/map/lib/map/struct.rb:27:in `method_missing'
/home/eddie/Coding/map/test/lib/testing.rb:47:in `assert'
test/map_test.rb:185:in `block (2 levels) in <main>'
===============================================================================
.......................................

Finished in 0.264128141 seconds.

57 tests, 4952 assertions, 0 failures, 2 errors, 0 pendings, 0 omissions, 0 notifications
96.4912% passed

Tests fail with jruby

With jruby (jruby 1.5.6 (ruby 1.8.7 patchlevel 249) (2011-06-08 6586) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_26) [amd64-java]) I get the following test failure:

/var/tmp/portage/dev-ruby/map-4.2.0/work/all/map-4.2.0/test/lib/testing.rb:23:in `Testing': undefined method `slug_for' for #<Class:01x11ba4159> (NoMethodError)
    from /var/tmp/portage/dev-ruby/map-4.2.0/work/all/map-4.2.0/test/lib/testing.rb:6:in `initialize'
    from /var/tmp/portage/dev-ruby/map-4.2.0/work/all/map-4.2.0/test/lib/testing.rb:6:in `new'
    from /var/tmp/portage/dev-ruby/map-4.2.0/work/all/map-4.2.0/test/lib/testing.rb:6:in `Testing'
    from /var/tmp/portage/dev-ruby/map-4.2.0/work/all/map-4.2.0/test/map_test.rb:4

Changing "def This.slug_for" to "def self.sluf_for" seems to fix this, and with this change the test suite still passes on ruby 1.8.7 and ruby enterprise edition. Haven't tried ruby 1.9.

Fails to load with ruby 1.9.2-p136

The library fails to load with an ArgumentError for Ruby 1.9.2 p136. Attached patches fix the loading and a typo in the code, but the tests still don't pass. The reason for this seems to be that the new Ruby calls 'inherited' before executing the block of Class.new do ... end. Therefore classes don't have names yet at #inherited.

https://gist.github.com/757123

greetings

map 6.2.0 fails tests

With ruby 1.8.7 (2012-06-29 patchlevel 370) [x86_64-linux] I'm seeing the following test failure:

=======================================================================================================================
@1 => /usr/bin/ruby18 -I ./lib -I ./test/lib /var/tmp/portage/dev-ruby/map-6.2.0/work/ruby18/map-6.2.0/test/map_test.rb
-----------------------------------------------------------------------------------------------------------------------
/var/tmp/portage/dev-ruby/map-6.2.0/work/ruby18/map-6.2.0/test/map_test.rb:420: syntax error, unexpected ')'
/var/tmp/portage/dev-ruby/map-6.2.0/work/ruby18/map-6.2.0/test/map_test.rb:764: syntax error, unexpected $end, expecting kEND
-----------------------------------------------------------------------------------------------------------------------
@1 <= FAILURE
-----------------------------------------------------------------------------------------------------------------------

#keep_if is failing to work as expected

Map#keep_if (from Hash) sets values to nil as opposed to deleting key/value pair

A failing test:

testing 'that Map#keep_if properly removes k/v pairs for which the passed block evaluates to false' do
  m = Map.new( { 1 => "hi" , 2 => "there" } )
  puts m.keep_if { |k,v| k == 2 }.inspect
  assert{ !( m.keep_if { |k,v| k == 2 }.keys.include? 1 ) }
end

Missing license

It is not clear under what license the code is release. Could you add licensing information?

"Unexpected" behavior

Maybe this is not really a bug, but not the way I expected the structure to begin, because it is inconsistent with Hash.

h = {}
(h[:a] ||= []) << :b
# h is now {:a=>[:b]}

m = Map.new
(m[:a] ||= []) << :b
# m is now {:a=>[]}

This helps to understand:

(m[:a] = {}).class # Hash
m[:a].class # Map
(m[:a] = {})[:b] = :c # m is {:a=>{}}
m[:a] = {}; m[:a][:b] = :c # m is {:a=>{:b=>:c}}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.