I'm trying out Rubymotion and can't seem to do figure how to accomplish what seems like a simple task.
I've set up a UITableView for a directory of people. I've created a rails back end that returns json.
Person model has a get_people class method defined:
def self.get_people
BubbleWrap::HTTP.get("http://myapp.com/api.json") do |response|
@people = BW::JSON.parse(response.body.to_str)
# p @people prints [{"id"=>10, "name"=>"Sam"}, {etc}] to the console
end
end
In the directory_controller I just want to set an instance variable for @data to the array that my endpoint returns such that I can populate the table view.
I am trying to do @data = Person.get_people
in viewDidLoad, but am getting an error message that indicates the BW response object is being passed instead: undefined method
count' for #BubbleWrap::HTTP::Query:0x8d04650 ...> (NoMethodError)`
So if I hard code my array into the get_people method after the BW response block everything works fine. But I find that I am also unable to persist an instance variable through the close of the BW respond block.
def self.get_people
BubbleWrap::HTTP.get("http://myapp.com/api.json") do |response|
@people = BW::JSON.parse(response.body.to_str)
end
p @people #prints nil to the console
# hard coding [{"id"=>10, "name"=>"Sam"}, {etc}] here puts my data in the table view correctly
end
What am I missing here? How do I get this data out of bubblewrap's response object and in to a usable form to pass to my controllers?
As explained in the BW documentation "BW::HTTP wraps NSURLRequest, NSURLConnection and friends to provide Ruby developers with a more familiar and easier to use API. The API uses async calls and blocks to stay as simple as possible."
Due to async nature of the call, in your 2nd snippet you are printing @people before you actually update it. THe right way is to pass the new data to the UI after parsing ended (say for instance @table.reloadData() if @people array is supposed to be displayed in a UITableView).
Here's an example:
def get_people
BubbleWrap::HTTP.get("http://myapp.com/api.json") do |response|
@people = BW::JSON.parse(response.body.to_str)
update_result()
end
end
def update_result()
p @people
# do stuff with the updated content in @people
end
Find a more complex use case with a more elaborate explanation at RubyMotion async programming with BubbleWrap