0

I have a perfectly functional piece of code that does what I want but it is really heavy and i am sure it could be greatly improved by using a nice For loop somewhere but I'm not sure how to go about it

My code is:

def helper
response = RestClient.get API_RESPONSE
check_X_0 = JSON.parse(response.body)['EXP'][0]['X']
check_Y_0 = JSON.parse(response.body)['EXP'][0]['Y']
check_X_1 = JSON.parse(response.body)['EXP'][1]['X']
check_Y_1 = JSON.parse(response.body)['EXP'][1]['Y']
check_X_2 = JSON.parse(response.body)['EXP'][2]['X']
check_Y_2 = JSON.parse(response.body)['EXP'][2]['Y']
check_X_3 = JSON.parse(response.body)['EXP'][3]['X']
check_Y_3 = JSON.parse(response.body)['EXP'][3]['Y']
check_X_4 = JSON.parse(response.body)['EXP'][4]['X']
check_Y_4 = JSON.parse(response.body)['EXP'][4]['Y']
if check_X_0 == false && check_Y_0 == true
  exp_id = JSON.parse(response.body)['EXP'][0]['ABC']
elsif check_X_1 == false && check_Y_1 == true
  exp_id = JSON.parse(response.body)['EXP'][1]['ABC']
elsif check_X_2 == false && check_Y_2 == true
  exp_id = JSON.parse(response.body)['EXP'][2]['ABC']
elsif check_X_3 == false && check_Y_3 == true
  exp_id = JSON.parse(response.body)['EXP'][3]['ABC']
elsif check_X_4 == false && check_Y_4 == true
  exp_id = JSON.parse(response.body)['EXP'][4]['ABC']
else
  puts 'Nothing valid - use default'
  exp_id = JSON.parse(response.body)['EXP'][1]['ABC']
end

This is fairly cumbersome so can anyone help me to trim this down?

  • 1
    Does [this](https://stackoverflow.com/questions/22132623/ruby-iterate-over-parsed-json) helps? – yorodm Aug 24 '18 at 14:52

1 Answers1

0

You should not parse your json 10 times in the first place. Parse it once and use the result.

rb = RestClient.get(API_RESPONSE).body['EXP']

checks = (0..4).map { |i, s| [i, rb[i]['X'], rb[i]['Y']]  }
exp_id =
  if found = checks.detect { |_i, f, t| !f && t }
    rb[found.first]['ABC']
  else
    puts 'Nothing valid - use default'
    rb[1]['ABC']
  end
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • This really helps, thanks! With the .detect function how are the arguments laid out here? I assume that the 'f' and 't' values are true false equivalent but how would this lay out if say the Y value was a string of "helloWorld"? I tried editing it about but i keep running into syntax errors... – Ian Pie Goddard Aug 28 '18 at 08:27
  • How about you put `puts [i, f, t].inspect` there and check it out yourself? The block arguments are always what the iterable (`checks` in this case) contains. Hence, they would be `[i, rb[i]['X'], rb[i]['Y']]` from the previous `map` call. – Aleksei Matiushkin Aug 28 '18 at 08:30
  • I am getting the right content, I had already seen that in a `puts checks` line but i am not sure where to put in my expected values in the `IF`. If I put in the values I want to look for in the `{ |-i,f,t|` part then i get syntax errors and if I put them into the `!f && t }` part then I'm not actually finding the values I put in, put actually just returning the value of ABC from the first `i` value in the iterable. I am sur ei'm missing something super obvious but I'm not sure I get it... – Ian Pie Goddard Aug 28 '18 at 08:59
  • `{ |_i, f, t| !f && t }` → `{ |i, f, t| puts([i, f, t].inspect); !f && t }`. – Aleksei Matiushkin Aug 28 '18 at 09:02
  • So this returns the first `i` value in the map. How can i get it to iterate through until it finds a specific combination of `X` response and `Y` response and return that `i` value into the `ABC` request? Say, if the combination I want is in the [3] position. – Ian Pie Goddard Aug 28 '18 at 09:21
  • `break i if condition`. – Aleksei Matiushkin Aug 28 '18 at 09:22
  • I'm not entirely sure this solution is doing what I need it too but it has helped me a huge amount, thanks! – Ian Pie Goddard Aug 28 '18 at 10:03