JBlake
JBlake

Reputation: 1064

Ruby: Best way to parse a conditional array element

I'm doing API calls that will conditionally return a couple different elements. My code is currently:

if array['productId']
  value = array['productId'][0]
end

I feel like there is a more succinct way of doing this. Some Ruby magic.

Upvotes: 0

Views: 1393

Answers (9)

Tim Raasveld
Tim Raasveld

Reputation: 111

Since Ruby 2.3.0, the shortest way is Array#dig:

array.dig('productId', 0)

http://ruby-doc.org/core-2.3.0_preview1/Array.html#method-i-dig

Upvotes: 2

brookr
brookr

Reputation: 1515

Ha, I love all the options here. But since I didn't see what I use most, I'll add one more!

value = array['productId'] && array['productId'].first

(I prefer .first to [0] because it reads a little better)

This presumes you'll have an array in array['productId'], which is the right way to do it (rather than type-checking).

Otherwise, the biggest diference between this and your original code, is that this results in value having nil assigned to it if the array doesn't have anything, whereas your original results in value not being defined (which may cause errors, depending on how you use it down the road).

Hope that helps!

Upvotes: 0

kikito
kikito

Reputation: 52651

This might be a bit pedantic, but to make sure it works in all circumstances, you should not check 'not-nil', but rather that it is indexable; something like this:

value = array['productId'][0] if array['productId'].is_a? Array

Or even better:

value = array['productId'][0] if array['productId'].respond_to? '[]'

Otherwise your code will fail if array['productId'] == 2 (which on the other hand seems reasonable, given the key used - I would have gone product_ids instead).

Upvotes: 1

Michael Kohl
Michael Kohl

Reputation: 66837

While I think your code is fine (although I'd prefer SpyrosP's one-line version), you have some possibilities:

  • Rails has Object#try, which would let you do either array['productId'].try(:[], 0) or array['productId'].try(:at, 0).

  • Some people like the andand gem, which defines Object#andand and is used like array['productId'].andand[0].

Upvotes: 0

tokland
tokland

Reputation: 67860

Using the maybe pattern of Ick, terse and explicit:

value = array['productId'].maybe[0]

Upvotes: 0

DigitalRoss
DigitalRoss

Reputation: 146073

Your code pattern looks OK; it's possible to be slightly shorter...

value = (t = x['productId']) && t[0]

Upvotes: 0

sawa
sawa

Reputation: 168101

I am not sure if you are using value just temporarily or actually using it later, and what you want to do with value when the condition is not met. If you want to return nil for missing keys, then

array['productId'].to_a[0]

can work. Otherwise, SpyrosP's answer will be the best.

Upvotes: 1

Spyros
Spyros

Reputation: 48626

A better way :

value = array['productId'][0] if array['productId']

However, array['productId'][0] is not ruby natural. What does your array consist of ?

Upvotes: 4

Joshua Smith
Joshua Smith

Reputation: 6621

You could use a ternary:

   value = array['productId'].nil?  ? nil : array['productId'][0]

Upvotes: 0

Related Questions