valid_json? check in ruby is not working - ruby

I am trying to check whether the response is valid JSON. I am making HTTParty or Restclient request to some urls and checking whether the responses returned are valid JSON?
I referred the link here. This is not working.
My code:
require 'json'
def get_parsed_response(response)
if not response.is_a? String or not response.valid_json?
# code
end
end
Error:
/home/user/.rvm/gems/ruby-2.1.0/gems/httparty-0.13.1/lib/httparty/response.rb:66:in `method_missing': undefined method `valid_json?' for #<HTTParty::Response:0x00000002497918> (NoMethodError)

More specifically than in my comment, I suggest you use something like this:
value = nil
begin
value = JSON.parse(response)
# do whatever you do when not error
rescue JSON::ParserError, TypeError => e
puts "Not a string, or not a valid JSON"
# do whatever you do when error
end

You should be calling response.body.
response is an HTTParty::Response object. What you really want to be working with is the String object that represents the HTTP response body.

Related

Correct way to get response from Slack API

I want to move this code from the console:
curl --data "token=TOKEN_NO&email=USER#EXAMPLE.COM" https://slack.com/api/users.lookupByEmail
to the class method and get response from Slack (user details) exactly like from the console. I was trying to do something like this, but I don't see any results:
require 'net/http'
module Slack
class GetUserID
SLACK_API_ENDPOINT = 'https://slack.com/api/users.lookupByEmail'
def call
escaped_address = URI.decode_www_form_component(SLACK_API_ENDPOINT)
uri = URI.parse(escaped_address)
puts Net::HTTP.post(uri, params)
end
private
def params
{
token: 'TOKEN_NO',
email: 'USER#EXAMPLE.COM'
}
end
end
end
Right now I have an error:
send_request_with_body': undefined methodbytesize' for #Hash:0x00007f9d85093100> (NoMethodError)
Where am I wrong? Should I use HTTParty instead?
The second argument passed to Net::HTTP.post should be a string, read more about the method signature here.
You will need to convert the params hash into a query string format that looks like:
token=TOKEN_NO&email=USER#EXAMPLE.COM

Httparty request query not parsed properly

I would like to pass some query parameters to HTTParty.get. I have a helper method to handle requests
def handle_request
begin
response = yield
if response['Success']
response['Payload']
else
raise Bondora::Error::ApiError, "#{response['Errors'][0]['Code']}: #{response['Errors'][0]['Message']}"
end
rescue Net::OpenTimeout, Net::ReadTimeout
{}
end
end
And another method to to make the request:
def investments(*params)
handle_request do
url = '/account/investments'
self.class.get(url, :query => params)
end
end
When I call this method like investments({"User" => "test"}) I should end up with a GET request to /account/investments?User=test.
Unfortunately the request params are not parsed properly and the resulting request looks like this: /account/balance?[{%22User%22=%3E%22test%22}]
Any clue why this happens? I think it has something to do with the methods I wrote.
When you declare the method as def investments(*params), params will contain an array of arguments, and want to pass a hash to your get call. So, either drop the asterisk and simply say def investments(params), or use query: params.first later in the method.

How to serialize Exception

According to ruby-doc and apidock, you can serialize and deserialize an exception using to_json and json_create.
But after having wasted some time trying to use them, I still haven't found a way.
Calling exc.to_json gives me an empty hash, and Exception.json_create(hash) gives me this error: undefined method 'json_create' for Exception:Class
I guess I could easily recreate those functions since the source is available, but I'd rather understand what I'm doing wrong... Any idea?
The JSON module doesn't extend Exception by default. You have to require "json/add/exception". I'm not sure if this is documented anywhere:
require "json/add/exception"
begin
nil.foo
rescue => exception
ex = exception
end
puts ex.to_json
# => {"json_class":"NoMethodError","m":"undefined method `foo' for nil:NilClass","b":["prog.rb:5:in `<main>'"]}
Check out ext/json/lib/json/add in the Ruby source to see which classes work this way. If you do require "json/add/core" it will load JSON extensions for Date, DateTime, Exception, OpenStruct, Range, Regexp, Struct, Symbol, Time, and others.
The answer from Jordan is correct. If you have a case eg. that you need to serialize an Exception and send to to ActiveJob where you want to reconstruct it, then you need to use .as_json method.
require "json/add/exception"
begin
nil.foo
rescue => exception
ex = exception
end
puts ex.to_json.class
# => String
string = ex.to_json
puts Exception.json_create(string).message
# => m
puts ex.as_json.class
# => Hash
hash = ex.as_json
puts Exception.json_create(hash).message
# => undefined method `foo' for nil:NilClass
You need to read the source code to understand why Exception.json_create(string).messagereturns m :)
It's also important to note that the Exception.json_create example doesn't keep the error class.
Exception.json_create(JSON.parse(ArgumentError.new('error').to_json))
# => #<Exception: error>
Try instead:
require "json/add/exception"
def deserialize_exception(json)
hash = JSON.parse(json)
hash['json_class'].constantize.json_create(hash)
end

get response of grape endpoint with def after

I'm using Grape. I want to define a method that runs after the response value has been calculated for a request, I tried following this:
http://www.sinatrarb.com/intro.html#Filters
and ended up with:
after do
puts response
end
however response is not defined. Apparently within this block, self refers to Grape::Endpoint, since after runs after the endpoint handler, I should be able to find the response value, right? I tried self.body however this returns nothing - it does, however, let me change the value of the response, but I want to retrieve the response value that was generated by my handler.
Ahh, so I solved this using rack middleware:
class CaptureResponse < Grape::Middleware::Base
def call!(env)
#env = env
#app_response = #app.call(#env)
body = #app_response[2]
body = body.body if body.kind_of? Rack::BodyProxy
puts body
#app_response
end
end
use CaptureResponse
I have no idea why just slapping in use CaptureResponse in config.ru works but it does!

undefined local variable or method `http' for main:Object Ruby

I have a header and url as specified below:
header = { 'User-Agent' => 'SubDB/1.0 (Subtitle-Downloader /1.0; https://github.com/gautamsawhney/Subtitle-Downloader)' }
url = "http://sandbox.thesubdb.com/?action=download&hash=" + hash + "&language=en"
I am try to send an HTTP get request using
send_request method in ruby. I am basically trying to access the SubDB API. I have written the following code to send a request :
res = http.send_request('GET', url, header)
puts res.body
I have also done this require net/http , but I get this error
undefined local variable or method `http' for main:Object (NameError)
Can someone tell me what's wrong and if can I use any other method for the same? The inclusion of the header is necessary.
In your example, You need to instantiate the Net::Http before using that
http = Net::HTTP.new "sandbox.thesubdb.com"
res = http.send_request("GET", "/?action=download....", nil, headers)

Resources