Get value from JSON response in Ruby - ruby

I am making a JSON call to a Ruby on Rails server via a client side ruby script, which returns the following JSON:
get_data.rb
require 'net/http'
require 'open-uri'
require 'json'
def get_functions(serial_number, function)
request_uri = "http://localhost:3000/devices/#{serial_number}"
buffer = open(request_uri).read
result = JSON.parse(buffer)
puts result
end
{ "serial_number" => "111aaa",
"device_functions" => [
{ "can_scan" => true,
"can_halt" => true
}
],
"host_options" => [
{ "exclude_ip" => "10.10.10.100-110",
"scan_ip" => "10.10.10.1"
}
]
}
Now, I'm wanting to just extract certain values from the response to determine what can/cannot be done on the client side:
scan.rb
if get_functions('111aaa', 'can_scan')
result = %x( ping 10.10.10.1 )
else
result = "Not allowed to perform action!"
end
I'm stuck with how I can extract the value of can_scan from my JSON in get_data.rb for my get_functions method to be able to run its if statement correctly.

Your get_functions is returning nil as the last line is an I/O operation (puts). Change your function to:
def get_functions(serial_number, function)
request_uri = "http://localhost:3000/devices/#{serial_number}"
buffer = open(request_uri).read
result = JSON.parse(buffer)
puts result
result
end
And access the Hash:
result = get_functions(serial_number, function)
result["device_functions"].first["can_scan"]

Related

Waitr and Jira integration not producing desired output

I wrote a Ruby script to check if the layer found in DOM in Firebug for the page www.jira.com is matching with the hash values declared in my script. Below is the Ruby script I have written:
require 'watir'
browser = Watir::Browser.new(:chrome)
browser.goto('https://jira.com')
JIRA_DATA_LAYER = {
'jira' => {
'event' => ['gtm.js', 'gtm.load'],
'gtm.start' => '1468949036556',
}
}
def get_jira_data_layer(get_data_layer)
result = []
get_data_layer.each do |data_layer|
data_layer.each do |data_layer_key, data_layer_value|
result << {"#{data_layer_key}" => data_layer_value}
end
end
return result
end
def compare_jira_data_layer(layer, jira_name)
message = []
index = 0
JIRA_DATA_LAYER[jira_name].each do |jira_key, jira_value|
if layer.include?({jira_key => jira_value})
result = 'matches - PASS'
else
result = 'matches - FAIL'
end
index += 1
message.push("'#{jira_key} => #{jira_value}' #{result}")
end
return message.join("\n")
end
data_layer = browser.execute_script("return dataLayer")
get_data_layer = get_jira_data_layer(data_layer)
compare_data_layer = compare_jira_data_layer(get_data_layer, "jira")
puts compare_data_layer
I am getting the following output:
'event => ["gtm.js", "gtm.load"]' matches - FAIL
'gtm.start => 1468949036556' matches - FAIL
I want the following to be achieved:
'event => gtm.js' matches - FAIL
'gtm.start => 1468949036556' matches - FAIL
You could simply change the value for event key in JIRA_DATA_LAYER, but I guess it has to be that way.
Try to expand if sentence when checking key for this hash and use is_a? method to check whether value for particular key is array or not. If so, loop through each member of this array.

Hash/string gets escaped

This is my hyperresource client:
require 'rubygems'
require 'hyperresource'
require 'json'
api = HyperResource.new(root: 'http://127.0.0.1:9393/todos',
headers: {'Accept' => 'application/vnd.127.0.0.1:9393/todos.v1+hal+json'})
string = '{"todo":{"title":"test"}}'
hash = JSON.parse(string)
api.post(hash)
puts hash
The hash output is: {"todo"=>{"title"=>"test"}}
At my Sinatra with Roar API I have this post function:
post "/todos" do
params.to_json
puts params
#todo = Todo.new(params[:todo])
if #todo.save
#todo.extend(TodoRepresenter)
#todo.to_json
else
puts 'FAIL'
end
end
My puts 'params' over here gets: {"{\"todo\":{\"title\":\"test\"}}"=>nil}
I found out, these are 'escaped strings' but I don't know where it goes wrong.
EDIT:
I checked my api with curl and postman google extension, both work fine. It's just hyperresource I guess
You are posting JSON, ergo you either need to register a Sinatra middleware that will automatically parse incoming JSON requests, or you need to do it yourself.
require 'rubygems'
require 'hyperresource'
require 'json'
api = HyperResource.new(root: 'http://127.0.0.1:9393/todos',
headers: {'Accept' => 'application/vnd.127.0.0.1:9393/todos.v1+hal+json'})
string = '{"todo":{"title":"test"}}'
hash = JSON.parse(string)
api.post({:data => hash})
puts hash
---
post "/todos" do
p = JSON.parse(params[:data])
puts p.inspect
#todo = Todo.new(p[:todo])
if #todo.save
#todo.extend(TodoRepresenter)
#todo.to_json
else
puts 'FAIL'
end
end
Should do what you need.

How to exit from async call when url timeout with ruby/curb

I am using Ruby curb to call multiple urls at once, e.g.
require 'rubygems'
require 'curb'
easy_options = {:follow_location => true}
multi_options = {:pipeline => true}
Curl::Multi.get(['http://www.example.com','http://www.trello.com','http://www.facebook.com','http://www.yahoo.com','http://www.msn.com'], easy_options, multi_options) do|easy|
# do something interesting with the easy response
puts easy.last_effective_url
end
The problem I have is I want to break the subsequent async calls when any url timeout occurred, is it possible?
As far as I know the current API doesn't expose the Curl::Multi instance, since otherwise you could do:
stop_everything = proc { multi.cancel! }
multi = Curl::Multi.get(array_of_urls, on_failure: stop_everything)
The easiest way might be to patch the Curl::Multi.http to return the m variable.
See https://github.com/taf2/curb/blob/master/lib/curl/multi.rb#L85
I think this will do exactly what you ask for:
require 'rubygems'
require 'curb'
responses = {}
requests = ['http://www.example.com','http://www.trello.com','http://www.facebook.com','http://www.yahoo.com','http://www.msn.com']
m = Curl::Multi.new
requests.each do |url|
responses[url] = ""
c = Curl::Easy.new(url) do|curl|
curl.follow_location = true
curl.on_body{|data| responses[url] << data; data.size }
curl.on_success {|easy| puts easy.last_effective_url }
curl.on_failure {|easy| puts "ERROR:#{easy.last_effective_url}"; #should_stop = true}
end
m.add(c)
end
m.perform { m.cancel! if #should_stop }

Ruby HTTP Post containing multiple parameters and a body

I need to post using three parameters and a body which consists of 512 bytes. I can get the body right but I can't seem to get the parameters to take:
require 'net/http'
#ip_address = Array['cueserver.dnsalias.com']
#cueserver = 0
#playback = 'p1'
def send_cuescript(data)
params = {'id' => '1', 'type' => "20",'dst' => 'RES' }
begin
url = URI.parse('http://'+ #ip_address[#cueserver] + '/set.cgi')
http = Net::HTTP.new(url.host, url.port)
response, body = http.post(url.path, params, data)
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
end
response_array = []
puts 'got this value: ' + response.to_s
response.body.each_byte { |e| response_array.push(e.to_s(16))}
end
data_array = Array.new(512, "\x80")
send_cuescript(data_array.join)
I am getting an error from the initialize_http_header. I know there must be a way to set the parameters and the body separately but I can't seem to find any reference to this.
Why do you have to send part of the params in the url and part of it in the body?
If you have to do this, try
url = URI.parse('http://'+ #ip_address[#cueserver] + '/set.cgi?' + params.to_param)
PS: to_param is from active support. You need to write your own if you are not using active support.

Parameters for a Ruby HTTP Put call

I'm having trouble getting parameters passed in an HTTP Put call, using ruby. Take a look at the "put_data" variable.
When I leave it as a hash, ruby says:
undefined method `bytesize' for #<Hash:0x007fbf41a109e8>
if I convert to a string, I get:
can't convert Net::HTTPUnauthorized into String
I've also tried doing just - '?token=wBsB16NSrfVDpZPoEpM'
def process_activation
uri = URI("http://localhost:3000/api/v1/activation/" + self.member_card_num)
Net::HTTP.start(uri.host, uri.port) do |http|
headers = {'Content-Type' => 'text/plain; charset=utf-8'}
put_data = {:token => "wBsB16NSrfVDpZPoEpM"}
response = http.send_request('PUT', uri.request_uri, put_data, headers)
result = JSON.parse(response)
end
if result['card']['state']['state'] == "active"
return true
else
return false
end
end
I've searched all around, including rubydocs, but can't find an example of how to encode parameters. Any help would be appreciated.
Don't waste your time with NET::HTTP. I used 'rest-client' and had this thing done in minutes...
def process_activation
response = RestClient.put 'http://localhost:3000/api/v1/card_activation/'+ self.member_card_num, :token => "wBsB1pjJNNfiK6NSrfVDpZPoEpM"
result = JSON.parse(response)
return result['card']['state']['state'] == "active"
end

Resources