frodo
frodo

Reputation: 51

Data fetching Ruby

I'm running this following API call and getting list to vhosts and passing to another API and getting some values, those works fine.

response = conn.get("/api/vhosts")
statistics = JSON.parse(response.body)

statistics.each do |vhosts|
  response1 = conn.get("/api/exchanges/#{vhosts["name"]}/direct_queue_exchange")
  statistics1 = JSON.parse(response1.body)
  statistics1.fetch("message_stats").fetch("publish_in_details").fetch("rate")    
end

sample output:

output -1 - {"error"=>"Object Not Found", "reason"=>"Not Found"}

output -2 - {"message_stats"=>{"publish_in_details"=>{"rate"=>0.0}, "publish_in"=>91, "publish_out_details"=>{"rate"=>0.0}, "publish_out"=>91}, "outgoing"=>[], "incoming"=>[], "user_who_performed_action"=>"user_122f5b58", "arguments"=>{}, "internal"=>false, "auto_delete"=>false, "durable"=>true, "type"=>"direct", "vhost"=>"vhost_2388ce36", "name"=>"direct_queue_exchange"}
    {"outgoing"=>[], "incoming"=>[], "user_who_performed_action"=>"user_d6b8f477", "arguments"=>{}, "internal"=>false, "auto_delete"=>false, "durable"=>true, "type"=>"direct", "vhost"=>"vhost_37892b86", "name"=>"direct_queue_exchange"}

I have ran into problem fetching values I want. For example in my code I'm fetching these values like "rate" and I'm getting this error: key not found: "message_stats" because some outputs doesn't contains keys that I'm looking

How can I ignore outputs like this {"error"=>"Object Not Found", "reason"=>"Not Found"}

Upvotes: 1

Views: 606

Answers (3)

nattfodd
nattfodd

Reputation: 1900

If I got your question right, there're several way to do that:

In Ruby 2.3 and above (thanks to @Steve Turczyn)

statistics1.dig('message_stats', 'publish_in_details', 'rate')

Almost like yours, second parameter of fetch sets default value if the key wasn't found:

statistics1.fetch("message_stats", {}).fetch("publish_in_details", {}).fetch("rate", nil)

Or you can do something like that:

message_stats = statistics1['message_stats']
next unless message_stats

publish_in_details = message_stats['publish_in_details']
next unless publish_in_details

publish_in_details['rate']

Upvotes: 1

Nitin
Nitin

Reputation: 7366

Other two also provide solution for your question, Below is description for same.

fetch(key_name) # get the value if the key exists, raise a KeyError if it doesn't
fetch(key_name, default_value) # get the value if the key exists, return default_value otherwise

So use below will solve your issue.

statistics1.fetch("message_stats", ()).fetch("publish_in_details", {}).fetch("rate", nil)

also you can check if error present or not, and then handle case accordingly.

if fetch("message_stats", false)
  statistics1.fetch("message_stats").fetch("publish_in_details").fetch("rate")
end

Upvotes: 0

SteveTurczyn
SteveTurczyn

Reputation: 36880

You can use the default option in #fetch to return an empty hash if the key isn't present.

statistics1.fetch("message_stats", ()).fetch("publish_in_details", {}).fetch("rate", nil)

Even simper would be the #dig method

statistics1.dig("message_stats", "publish_in_details", "rate")

If any keys are missing, nil is gracefully returned.

Upvotes: 1

Related Questions