C.J. Bordeleau
C.J. Bordeleau

Reputation: 307

How do you iterate over and retrieve values from a hash with arrays?

I am trying to build a quick hack that "likes" all the recent photos on instagram of a particular tag.

I have authenticated and used the JSON gem to turn the JSON from the API into a Ruby Hash like this:

def get_content (tag_name)

   uri = URI.parse("https://api.instagram.com/v1/tags/#{tag_name}/media/recent? access_token=#{@api_token}")

   http = Net::HTTP.new(uri.host, uri.port)
   http.use_ssl = true
   http.verify_mode = OpenSSL::SSL::VERIFY_NONE

   request = Net::HTTP::Get.new(uri.request_uri)

   json_output = http.request(request)
   @tags = JSON.parse(json_output.body)

end

This outputs a hash with arrays as keys nested like the original JSON ( ex. http://instagr.am/developer/endpoints/tags/)

I am trying to iterate over and retrieve all the "id"s of the photos.

However when I use each method:

@tags.each do |item| 
  puts item["id"]
end

I get an error:

instagram.rb:23:in `[]': can't convert String into Integer (TypeError)
from instagram.rb:23:in `block in like_content'
from instagram.rb:22:in `each'
from instagram.rb:22:in `like_content'
from instagram.rb:42:in `<main>'

Upvotes: 3

Views: 8628

Answers (1)

Jordan Running
Jordan Running

Reputation: 106027

instagram.rb:23:in `[]': can't convert String into Integer (TypeError)

You're getting this error because in puts item["id"], item is an Array, not a Hash, so Ruby tries to convert what you put between [] into an integer index, but it can't because it's a string ("id").

This arises from the fact that json_output.body is a Hash. Take a second look at the example JSON response in the documentation:

{ "data" : [
    { "type"     : "image",
      // ...
      "id"       : "22699663",
      "location" : null
    },
    // ...
  ]
}

This whole structure becomes a single Hash with one key, "data", so when you call @tags.each you're actually calling Hash#each, and since "data"'s value is an Array when you call item["id"] you're calling Array#[] with the wrong kind of parameter.

Long story short, what you actually want to do is probably this:

@tags = JSON.parse( json_output.body )[ "data" ]

..then @tags will be the Array you want instead of a Hash and you can iterate over its members like you wanted:

@tags.each do |item| 
  puts item["id"]
end

Upvotes: 15

Related Questions