What's the easiest way to check if param[:x][:y] exists?

Hi all

In PHP I can simply check whether $param[‘x’][‘y’] exists regardless
whether $param[‘x’] exists or not.
In Rails I get a NoMethodError when using

if param[:x][:y]

end

when param[:x] is nil. So I always have to use

if param[:x] and param[:x][:y]

end

but I think that’s not very beautiful - think about a case where I have
to check whether param[:a][:b][:c][:d][:…] exists or not!

Maybe there’s a cooler way to do this? :wink:

Thanks
Josh

It looks to me as if you should be able to check for nil.

foo( param[:x][:y] ) unless (param[:x][:y] == nil)

Hi –

On Wed, 13 Aug 2008, Joshua M. wrote:

when param[:x] is nil. So I always have to use

if param[:x] and param[:x][:y]

end

but I think that’s not very beautiful - think about a case where I have
to check whether param[:a][:b][:c][:d][:…] exists or not!

Maybe there’s a cooler way to do this? :wink:

Yes: design your data structures with classes and modules and methods,
instead of quintuply-nested hashes :slight_smile: But if you want to have a hash
that automatically inserts a hash for an unknown key, you can do:

func = lambda {|h,k| h[k] = Hash.new(&func) }
hash = Hash.new(&func)

I think that’s the OK version… You can also rescue NoMethodError,
though that’s kind of fuzzy with lots of nesting.

David

Shadowfirebird wrote:

It looks to me as if you should be able to check for nil.

foo( param[:x][:y] ) unless (param[:x][:y] == nil)

I tried it on IRB, but it doesn’t seem to work.

David A. Black wrote:

Maybe there’s a cooler way to do this? :wink:

Yes: design your data structures with classes and modules and methods,
instead of quintuply-nested hashes :slight_smile:

You’re right, I just saw that I don’t need such a nested hash… :wink:

Sorry, you’re right:

irb(main):001:0> a = {:a=>{:x=>1}}
=> {:a=>{:x=>1}}
irb(main):003:0> p a[:a][:x]
1
=> nil
irb(main):004:0> p a[:a][:y]
nil
=> nil
irb(main):005:0> p a[:b][:x]
NoMethodError: undefined method `[]’ for nil:NilClass
from (irb):5

David’s much smarter than me, so listen to him…

On Tue, Aug 12, 2008 at 5:18 PM, Shadowfirebird

On Tuesday 12 August 2008, Joshua M. wrote:

when param[:x] is nil. So I always have to use
Thanks
Josh

You can use the rescue modifier, like this:

if (param[:x][:y] rescue nil)

end

The expression in brackets will return the value of param[:x][:y] but if
param[:x][:y] raises an exception derived from StandardError (like
NoMethodError), the exception will be caught by the rescue modifier, and
the
statement to the right of rescue (nil) will be returned.

I hope this helps

Stefano

foo( param[:x][:y] ) unless (param[:x][:y] == nil)

That only works if param[:x] exists. It’s also not perfect, since
[aram[:x][:y] can return a non-nil value if param[:x] exists but is
not an array… so you probably need to check for that case also.

To my knowledge, the only way you could handle this easily would be to
rescue the NoMethodError as follows:

param[:x][:y] rescue NoMethodError { nil } # return nil if
NoMethodError is raised

Although that’s tricky too, as depending on the nature of your object
structure, you may catch a NoMethodError you didn’t intend to catch.

Hope that helps.

–Tommy M.

2008/8/12 David A. Black [email protected]:

But if you want to have a hash
that automatically inserts a hash for an unknown key, you can do:

func = lambda {|h,k| h[k] = Hash.new(&func) }
hash = Hash.new(&func)

David, hashes like this don’t solve Josh’s problem. He wants two
conflicting things:

  1. param[:x][:y] should be false or nil, so that you can use it as a
    condition
  2. you should be able to nest arbitrarily deep, for example
    param[:x][:y][:z]

If Josh really wanted to do that, he’d have to define FalseClass#[] or
NilClass#[], but as you have written he’d better change his data
structures.

Regards,
Pit