0

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.

2
  • 2
    I think this is a hash, not an array. Also, I'm not sure there's anything more succinct than what you have: "If the element exists, than interact with it in a more specific way." You don't get much more succinct than a conditional, unless you're doing this process over and over and would benefit from a loop. Commented May 21, 2011 at 2:29
  • Basically I'm creating an object and saving it to Active Record. when the model has 10+ fields it feels very unnecessary to have 10 different conditionals to pull the data from. Also see my response to SpyrosP Commented May 21, 2011 at 3:38

9 Answers 9

4

A better way :

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

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

Sign up to request clarification or add additional context in comments.

2 Comments

Its a JSON response from eBay's API. I read the string and use JSON.parse. I think Matchu might be right that I'm actually dealing with a hash. In that case, am I doing this wrong altogether? Essentially I'm grabbing a couple key data fields from the JSON and saving them into my ActiveRecord database in the form of a Product model. (title, price, gallery_image, etc). I do like the solution presented.... keeps it all on one line, I hate nesting things.
value = array['productId'].try(:[], 0)
2

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

Comments

1

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.

Comments

1

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).

Comments

0

You could use a ternary:

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

Comments

0

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

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

Comments

0

Using the maybe pattern of Ick, terse and explicit:

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

Comments

0

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].

2 Comments

Note: the try method is added to Rails via ActiveSupport, and won't work in plain Ruby: guides.rubyonrails.org/active_support_core_extensions.html#try
Hence "Rails has Object#try" ;-)
0

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!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.