3

I find myself having to do this all the time, and when I'm in a hurry I wrap it in a conditional:

if !myhash.blank?
  hash.each do |k,v|
    do_something
  end
end

or:

myhash.map{|k,v| do_something} unless myhash.blank?

There must be something cleaner.

RubyRedGrapefruit
  • 12,066
  • 16
  • 92
  • 193
  • You could use a "null" hash that you set to return some acceptable default value. That is, you would define hash as `hash = my_hash || default_hash`. Then you don't need a conditional each time you refer to `my_hash`; just when it's first defined. – lwassink Jul 04 '16 at 20:17
  • Since an empty hash is a fine value to be looped over, you don't need the `blank?`: `if myhash` – tokland Jul 04 '16 at 21:05
  • 2
    If you have `nil` where you expect a `Hash`, that's a bug, and the correct response is to fix the bug so you don't get `nil` in the first place, not to work around the `nil`! And if you "find yourself having to do this all the time", then you have a *lot* of bugs, and you should tighten up your design, development, testing, code review, and QA processes (and, ultimately, your *hiring* processes, so you don't hire programmers that write such silly bugs in the first place)! – Jörg W Mittag Jul 05 '16 at 00:11
  • 1
    Thanks so much Jorg. I write the code from home for my business. Sorry for being so silly. But since we're giving out advice, my advice to you is to work on your manners. I don't care what your score is on SO, your arrogance is showing. – RubyRedGrapefruit Jul 05 '16 at 03:07
  • http://imgur.com/o3fNPon – RubyRedGrapefruit Jul 05 '16 at 03:12

5 Answers5

8

I tend to use to_h to hide the "is it nil" test:

hash.to_h.each do |k,v|
  # something
end

If hash is already a Hash then hash.to_h is hash, if hash.nil? then hash.to_h is { }.

Similarly, I use to_a for arrays:

array.to_a.each { |e| ... }

to_s for strings, to_i for integers (when I want to treat nil as zero), ...

mu is too short
  • 426,620
  • 70
  • 833
  • 800
5

I would probably do either this:

(my_hash || {}).each do |k, v|
  # something
end

or this:

my_hash ||= {}
my_hash.each do |k, v|
  # something
end
alf
  • 18,372
  • 10
  • 61
  • 92
  • +1 for the first snippet. I cannot say I like the second, though, variable re-bindings aren't too nice. Maybe later in the method you'll need the original value of `my_hash`. – tokland Jul 04 '16 at 21:10
3

If you are using rails, you can say:

my_hash.try(:each) do |key, value|
  # code
end

try will return nil if called on nil or if receiver does not respond to the method.

Petr Gazarov
  • 3,602
  • 2
  • 20
  • 37
3

If you want to specifically iterate if not nil you could do something like

hash && hash.each do |x|
  # do something
end

But I find the unless hash.nil? to be more expressive.

Damon
  • 4,216
  • 2
  • 17
  • 27
0
Hash(myhash).each {|k,v| # whatevs }

Always returns a Hash. Modified from: https://stackoverflow.com/a/18894072/1076207

irb test:

# $ irb
# irb(main):001:0> Hash(myhash=nil).each {|k,v|}
# => {}
# irb(main):002:0> Hash(myhash={"a" => "b"}).each {|k,v|}
# => {"a"=>"b"}
Community
  • 1
  • 1
SoAwesomeMan
  • 3,226
  • 1
  • 22
  • 25