tags:

views:

54

answers:

4

Can I create a Ruby Hash from a block?

Something like this (although this specifically isn't working):

foo = Hash.new do |f|
  f[:apple] = "red"
  f[:orange] = "orange"
  f[:grape] = "purple"
end
+2  A: 

I cannot understand why

foo = {
  :apple => "red",
  :orange => "orange",
  :grape => "purple"
}

is not working for you?

I wanted to post this as comment but i couldn't find the button, sorry

gkaykck
You raise a good point :)
@gkaykck you need 50 reputation before you can post comments. You should be able to leave comments now your answer has been upvoted.
mikej
thanks, i guess i should read the rules first :D
gkaykck
+2  A: 

In Ruby 1.9 (or with ActiveSupport loaded, e.g. in Rails), you can use Object#tap, e.g.:

foo = Hash.new.tap do |bar|
  bar[:baz] = 'qux'
end

You can pass a block to Hash.new, but that serves to define default values:

foo = Hash.new { |hsh, key| hsh[key] = 'baz qux' }
foo[:bar]   #=> 'baz qux'

For what it's worth, I am assuming that you have a larger purpose in mind with this block stuff. The syntax { :foo => 'bar', :baz => 'qux' } may be all you really need.

wuputah
I have a fixture file that is more or less a bunch of ActiveRecord create method calls. Wanted to pretty it up for readability.
A: 

What's wrong with

foo = {
  apple:  'red',
  orange: 'orange',
  grape:  'purple'
}
Jörg W Mittag
A: 

Passing a block to Hash.new specifies what happens when you ask for a non-existent key.

foo = Hash.new do |f|
  f[:apple] = "red"
  f[:orange] = "orange"
  f[:grape] = "purple"
end
foo.inspect # => {}
foo[:nosuchvalue] # => "purple"
foo # => {:apple=>"red", :orange=>"orange", :grape=>"purple"}

As looking up a non-existent key will over-write any existing data for :apple, :orange and :grape, you don't want this to happen.

Here's the link to the Hash.new specification.

Andrew Grimm