Using result of `JSON.decode` in Rails - ruby-on-rails

So I have an action in my controller that does a get_response to an API:
def memeapi
require "net/http"
require "uri"
#meme = Meme.new(params[:meme])
url = "http://version1.api.memegenerator.net/Instance_Create?username=apigen&password=SECRET&languageCode=en&generatorID=#{#meme.memeid}&imageID=#{#meme.imgid}&text0=#{#meme.text0}&text1=#{#meme.text1}"
resp = Net::HTTP.get_response(URI.parse(url))
data = resp.body
# I want to convert it to the Rails data structure - a hash
result = ActiveSupport::JSON.decode(data)
end
Ok but now I want to get back the information, use it to create another object, but I cant even format the information I am getting, can anyone tell me what I am doing wrong, what am I missing?
I want to be able to access the information from the get_response...
Thank you.
This is the JSON structure
{"success":true,"result":{"generatorID":45,"displayName":"Insanity Wolf","urlName":"Insanity-Wolf","totalVotesScore":0,"imageUrl":"/cache/images/400x/0/0/20.jpg","instanceID":13226270,"text0":"push","text1":null,"instanceImageUrl":"/cache/instances/400x/12/12916/13226270.jpg","instanceUrl":"http://memegenerator.net/instance/13226270"}}
I dont want to save all the fields btw...

result will look something like this after JSON.decode in your code.
{
'success' => true,
'result' => {
"generatorID" => 45,
"displayName" => "Insanity Wolf",
"urlName" => "Insanity-Wolf",
"totalVotesScore" => 0,
"imageUrl" => "/cache/images/400x/0/0/20.jpg",
"instanceID" => 13226270,
"text0" => "push",
"text1" => nil,
"instanceImageUrl" => "/cache/instances/400x/12/12916/13226270.jpg",
"instanceUrl" => "http://memegenerator.net/instance/13226270"
}
}
You have a nested hash (hash as part of a hash) here, which you can access like this:
image_url = result['result']['imageUrl'] # => "/cache/images/400x/0/0/20.jpg"
What you actually want to do with this information, I cannot guess. Maybe you want to update the Meme object you created?
#meme.url = image_url

Related

Appending to a JSON Array in a loop

Need to submit an HTTP POST request of a json string.
Have all of the RESTful parts working, and verified correctly.
This works if I hard code the elements inside the array. I am wanting to loop through one of the arrays in the JSON string, the "Attachments Array".
The loop would look something like:
#days = Daily.all
#days[0..11] do |dailys|
#loop that builds json to post
end
#RESTful HTTP POST request
The only problem is, I don't know how to implement a loop inside of a JSON string for only one array.
My code so far for testing out the HTTP POST
#!/usr/bin/ruby
require 'net/http'
require 'uri'
require 'json'
require 'jbuilder'
uri = URI.parse("<POST URL>")
header = {'Content-Type' => 'text/json'}
payload = {
channel: "<channel>",
username: "<username>",
# Wish to loop through the "Attachments" Array
attachments: [
{
param: "Text",
text: "Text",
pretext: "Optional Text",
color: 'good',
fields: [
{
Title: "Title field",
value: "First Value",
short: false
},
{
title: "Field Title",
value: "Field Value",
short: true
},
{
title: "Second Field Title",
value: "Second Field Value",
short: true
}
]
}
]
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri.request_uri, header)
req.body = payload.to_json
resp = http.request(req)
puts resp
Your code is looping through a bunch of Daily objects (though you're calling each one 'dailys' inside the loop which is confusing). You don't really explain what you want to do, but if you wanted to make a json object using some of the attributes of the Daily objects you have, you could do it like this.
hash = Daily.find(:all, :limit => 12).map{|daily| {:foo => daily.bar, :chunky => daily.chicken}}.to_json
If you give some details of the json string you want to make from your daily objects then i could give you some less silly code, but the approach is correct: build a ruby data structure then convert it to json with to_json
EDIT: following on from your comment, i would do this.
hash = Daily.find(:all, :limit => 12, :order => "id desc").map{|daily| {param: daily.title, fields: [{title: "Task Completed?", value: daily.completed, short: true}]} }
json = hash.to_json
Couple of notes:
1) Daily is a class, not an object (while classes are also objects in Ruby, i think that in rails it's better to refer to it as the class.
2) By the last 12 elements i assume you mean the most recently saved records: this is what the :order option is for.

Get value from a Rails nested hash

I have a Rails nested hash as follow:
class = [{"tutor" => {"id" => "Me"}}, {"tutor" => {}}]
I would like to extract id list, but the nested hash can be nil:
tutor_ids = class.map {|c| c['tutor']['id'].to_i }
In case the nested hash is nil, I'll get error.
How do I go about this?
First of all I think you were probably thinking of an array of hashes like so (given the same key was used multiple times:
klass = [{"tutor" => {"id" => "Me"}},{"tutor" => {}}]
Then you could map the tutor IDs with:
tutor_ids = klass.map {|k| k['tutor'] && k['tutor']['id'] }.compact
which would result in
=> ["Me"]
Compact will throw out all the nil values encountered afterwards.
id = class['tutor'] ? class['tutor']['id'] : nil

Providing a json response that references a local variable

I am trying to restructure a named-JSON response to return a model object (some attributes only), and some associated arrays stored in local variables, however I am unsure what I'm doing incorrectly. The local variables are definitely being assigned with values, however they're not being returned in the response.
This is the structure of what I want returned...
{ name: "Dan", email: "email#email.com", id: "1", open_gifts: [ { objects }, { here }] }
Setup
#person = Person.find_by_id(params[:id])
gifts_created_open = Gift.created_gifts_open(#person)
return_object = [#person.name, #person.email, #person.id, gifts_created_open]
Now this, returns a JSON object with the details, but its wrapped in an array, and I'm trying to return just a named object, with the associated array inside it.
render :json => return_object
And this returns a named object, but its missing the array. What gives??
render :json => #person.to_json(:gifts_created_open, :only => [:name, :email, :id] )
Many thanks with this. I've already spent several hours :/
Try:
return_object = {name:#person.name, email:#person.email, id:#person.id, gifts:gifts_created_open}.to_json

Take array and convert to a hash Ruby

I am trying this for the first time and am not sure I have quite achieved what i want to. I am pulling in data via a screen scrape as arrays and want to put them into a hash.
I have a model with columns :home_team and :away_team and would like to post the data captured via the screen scrape to these
I was hoping someone could quickly run this in a rb file
require 'open-uri'
require 'nokogiri'
FIXTURE_URL = "http://www.bbc.co.uk/sport/football/premier-league/fixtures"
doc = Nokogiri::HTML(open(FIXTURE_URL))
home_team = doc.css(".team-home.teams").map {|team| team.text.strip}
away_team = doc.css(".team-away.teams").map {|team| team.text.strip}
team_clean = Hash[:home_team => home_team, :away_team => away_team]
puts team_clean.inspect
and advise if this is actually a hash as it seems to be an array as i cant see the hash name being outputted. i would of expected something like this
{"team_clean"=>[{:home_team => "Man Utd", "Chelsea", "Liverpool"},
{:away_team => "Swansea", "Cardiff"}]}
any help appreciated
You actually get a Hash back. But it looks different from the one you expected. You expect a Hash inside a Hash.
Some examples to clarify:
hash = {}
hash.class
=> Hash
hash = { home_team: [], away_team: [] }
hash.class
=> Hash
hash[:home_team].class
=> Array
hash = { hash: { home_team: [], away_team: [] } }
hash.class
=> Hash
hash[:hash].class
=> Hash
hash[:hash][:home_team].class
=> Array
The "Hash name" as you call it, is never "outputed". A Hash is basically a Array with a different index. To clarify this a bit:
hash = { 0 => "A", 1 => "B" }
array = ["A", "B"]
hash[0]
=> "A"
array[0]
=> "A"
hash[1]
=> "B"
array[1]
=> "B"
Basically with a Hash you additionally define, how and where to find the values by defining the key explicitly, while an array always stores it with a numerical index.
here is the solution
team_clean = Hash[:team_clean => [Hash[:home_team => home_team,:away_team => away_team]]]

Ruby soap4r build headers

Again with the soap.
I am trying to build a header using soap4r that is supposed to look like this
<SOAP-ENV:Header>
<ns1:UserAuthentication
SOAP-ENV:mustUnderstand="1"
SOAP-ENV:actor="http://api.affiliatewindow.com">
<ns1:iId>*****</ns1:iId>
<ns1:sPassword>*****</ns1:sPassword>
<ns1:sType>affiliate</ ns1:sType>
</ns1:UserAuthentication>
<ns1:getQuota SOAP-ENV:mustUnderstand="1" SOAP-
ENV:actor="http://api.affiliatewindow.com">true</ns1:getQuota>
</SOAP-ENV:Header>
What I have done is created a header derv. class
AffHeader < SOAP::Header::SimpleHandler
Created a UserAuthentification element.
def initialize
#element = XSD::QName.new(nil, "UserAuthentification")
super(#element)
end
And return a hash
def on_simple_outbound
self.mustunderstand = 1
{ "iId" => ID, "sPassword" => PASSWORD, "sType" => "affiliate" }
end
How can I make my header look like I want further. How do I add the actor for example.
I am going to keep searching on this, any Help is very appreciated.
Thank you
In SOAP4R, the target_actor attribute is read only but you can add a new method like:
def target_actor= (uri)
#target_actor = uri
end
and in your on_simple_outbound method, you can call target_actor with your uri like so:
def on_simple_outbound
self.mustunderstand = 1
self.target_actor = "http://api.affiliatewindow.com"
{ "iId" => ID, "sPassword" => PASSWORD, "sType" => "affiliate" }
end
E.g.
irb(main):003:0> h = AffHeader.new
=> #<AffHeader:0x3409ef0 #target_actor=nil, #encodingstyle=nil,
#element=#<XSD::QName:0x1a04f5a {}UserAuthentification>,
#mustunderstand=false, #elename=#<XSD::QName:0x1a04f5a {}UserAuthentification>>
irb(main):006:0> h.on_simple_outbound
=> {"sType"=>"affiliate", "sPassword"=>"secret", "iId"=>"johndoe"}
irb(main):007:0> h
=> #<AffHeader:0x3409ef0 #target_actor="http://api.affiliatewindow.com",
#encodingstyle=nil,
#element=#<XSD::QName:0x1a04f5a {}UserAuthentification>,
#mustunderstand=1, #elename=#<XSD::QName:0x1a04f5a
{}UserAuthentification>>

Resources