Will Will - 2 years ago 99
Ruby Question

How to chain a dereference in ruby?

I'd like a method

t.find_first [:a, :b, :c], [:d, :e]
for a hash
that returns the first set of keys that dereference.

For the example above, it would be the equivalent of
t.try(:[], :a).try(:[], :b).try(:[], :c) || t.try(:[], :d).try(:[], :e)

Currently I'm at:

def find_first t, *keysets
keysets.each do |keys|
val = val || keys.inject(t){ |h, key| h.try(:[], key) }

Answer Source

There is no reason to create a special method for this.

Ruby < 2.3

value   = t.try(:[], :a).try(:[], :b).try(:[], :c)
value ||= t.try(:[], :d).try(:[], :e)

Ruby >= 2.3:

value   = t&.[](:a)&.[](:b)&.[](:c)
value ||= t&.[](:d)&.[](:e)

And while this question was posed rather obliquely, it looks from the method signature that you might be trying to walk into a nested hash like a params object.

If that is the case, you should take a look at Hash#dig for this. You can always monkeypatch it in if you aren't on 2.3

value   = t.dig(:a, :b, :c)
value ||= t.dig(:d, :e)

Another pattern for walking into hashes without Hash#dig is something like this:

params.fetch(:a, {}).fetch(:b, {})[:c]
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download