743: unexpected token at '... in Ruby on Rails - ruby-on-rails

I saved a file named array.json on my Dropbox folder and i access to it via Dropbox API. All works fine, but when i retrieve JSON content i cannot JSON.parse that string!!
session = DropboxSession.new(APP_KEY, APP_SECRET)
session.set_access_token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET)
client = DropboxClient.new(session, ACCESS_TYPE)
json = client.get_file(DIRECTORY + '/array.json')
#json = JSON.parse json
Error:
743: unexpected token at '{"Nome" : "Mario Rossi",
"C.F." : "ABCDEFGHILMNOP",
"Booking Assistance" : "MARIO",
"Status of reservation" : "25/11/2011"}'
JSON string is valid!! if i copy this string and paste it (manually) as parameter in JSON.parse(), json is parsed correctly!! So i think is a encoding problem...but where i wrong?

We have abandoned the json parsing backend that is the default in Rails. The default backend is YAML based and imo a useless mess. After several gotchas parsing unicode, and dates in some cases, we discovered that the backend can be replaced via configuration.
You can substitute the parsing backend in an initializer
ActiveSupport::JSON.backend = "JSONGem"
There are several gems that can be used as the backend, we just use the json gem
gem 'json'

Related

Ruby - no implicit conversion of HTTParty::Response into String exotel api

I'm unable to fetch response or send request to exotel sms api using the provided documentation on exotel rubygem http://www.rubydoc.info/gems/exotel/0.2
The documentations says to fetch response as follows:
sms = Exotel::Sms.details(sms_id)
But when I do that with an sms_id, ex. sms_id='12345678901234567890'
like
sms = Exotel::Sms.details("12345678901234567890")
it gives an error
TypeError: no implicit conversion of HTTParty::Response into String
I do have httparty gem installed. How to solve this?
The library is tested with 0.9.0 version of httparty that used to respond with Hash for http requests and the code is assuming it is string if not Hash and that is why it is failing
Here is the line causing the problem
exotel/response.rb
Quick fix would be to use 'httparty=0.9.0'
You may do it by using
gem "httparty","0.9.0"
Here is a working sample code, please update the account_sid and token with yours
gem "httparty","0.9.0"
require "exotel"
account_sid = "testexotel"
token = "9dcb4*******************e1dc2174fc47"
Exotel.configure do |c|
c.exotel_sid = account_sid
c.exotel_token = token
end
sms = Exotel::Sms.details("40a7*********258d411898b18b")
puts sms.status
puts sms.date_sent

Read JSON formatted response from Google finance api

The code for get data from google-finance url:
uri =URI.parse('http://finance.google.com/finance/info?client=i&q=NSE:ANDHRABANK')
rs = Net::HTTP.get(uri)
rs.delete! '//'
a = JSON.parse(rs)
p a
This is the response:
[{"id"=>"15355585", "t"=>"ANDHRABANK", "e"=>"NSE", "l"=>"49.30", "l_fix"=>"49.30", "l_cur"=>"₹49.30", "s"=>"0", "ltt"=>"3:30PM GMT+5:30", "lt"=>"Jan 13, 3:30PM GMT+5:30", "lt_dts"=>"2017-01-13T15:30:00Z", "c"=>"-0.15", "c_fix"=>"-0.15", "cp"=>"-0.30", "cp_fix"=>"-0.30", "ccol"=>"chr", "pcls_fix"=>"49.45"}]
Unable to access the JSON array. Want to access the array in a['t'] manner.
Since you're dealing with a hash in an array, you have to specify the array element position as well:
require 'json'
require 'net/http'
uri = URI.parse('http://finance.google.com/finance/info?client=i&q=NSE:ANDHRABANK')
rs = Net::HTTP.get(uri)
rs.delete! '//'
a = JSON.parse(rs)
p a.class #=> Array
p a[0]["t"] #=> "ANDHRABANK"
Either you run loop on array then you can access using a[i]["t"] or use a[0]["t"].
Note: i is the index of array elements.
You aren't making it easy for yourself. Consider this:
require 'json'
require 'open-uri'
rs = open('http://finance.google.com/finance/info?client=i&q=NSE:ANDHRABANK').read
foo = JSON[rs[4..-1]].first
foo['t'] # => "ANDHRABANK"
Rather than deal with the intricacies of Net::HTTP, which is more useful as a tool to build new HTTP services, I'd recommend relying on OpenURI, or one of the many HTTP clients available. The advantage over Net::HTTP is redirection is automatically handled plus simplicity. OpenURI does have some downsides, but for a basic URL getter it's fine.
The JSON class has [] which is smart enough to convert a string into the corresponding Ruby object. It'll also serialize a Ruby object back into a String:
puts JSON[{'a' => 1}]
# >> {"a":1}
The service you're calling is returning JSON, only, in this case, it's a single-element array containing a hash. Using first makes it easy to retrieve the hash and access it normally. It's cleaner to do that than to sprinkle your code with this form:
foo[0]['t']
which is longer to type and results in a visual noise.

Ruby SOAP Client using SAVON not working whereas PHP SOAP client works

Hello there I am testing few web services and I am trying to write a client using SAVON with my WSDL. I have one available operation named log_process and I am trying to access that but getting errors. I have a similar script written in PHP and it is working fine. I have tried
require 'net/http'
require "uri"
require 'savon'
client = Savon.client(wsdl: "http://somedomain.com/projects/shared/abc.wsdl")
#a=client.operations
puts #a
ary={0 =>"art", 1 =>"bac", 2 =>"arr"}
#result = client.call(:log_process, message:{0 =>"asdf", 1 =>"qwer", 2 =>"arr"})
puts #result
and getting following error
raise_soap_and_http_errors!': (SOAP-ENV:Client) Bad Request (Savon::SOAPFault)
My php working solution looks like this
$result = $client->log_process(array(0=>$user_name,1=>$user_pwd,2=>$display_type));
any idea what will be the ruby equivalent to this or am I calling the operation in correct manner?
I know this is late, but I was having the exact same issue trying to set up a soap request using savon to a soap server I have worked with extensively using PHP Soap server. I found another post related to this, and it seem that adding the message_tag option fixed it.
This is because in my case the WSDL was expecting functionNameRequest in the xml, but savon as only sending funcionName by setting message_tag to functionNameRequest the >soap server was able to correctly map the function that was being requested.
This was the thread that helped me out https://github.com/savonrb/savon/issues/520 Relevant code quoted below:
Hi,
I'm just sharing this in case it's useful.
I'm using savon 2.3.0 and I guess the gem had some problems identifying parameters >automatically from my wsdl. I have no idea about SOAP and this is the first time I'm >actually using it.
I'm dealing with TradeTracker's WSDL
With the following code I got it working:
client = Savon.client do
wsdl "http://ws.tradetracker.com/soap/affiliate?wsdl"
namespace_identifier :ns1
end
credentials = {
customerID: 123123,
passphrase: "123123123"
}
response = client.call(:authenticate, message_tag: :authenticate, message: credentials)
Try:
#result = client.call(:log_process, message:["asdf", "asg", "arr"])
In the PHP code, you are sending only 1 parameter, its an array

Twitter Application Only Auth

I'm trying to get an Application Only Auth token following the steps of this link:
https://dev.twitter.com/docs/auth/application-only-auth
I'm using Ruby on Rails and Rest Client to make the POST request needed and I'm setting the headers (I think) properly.
The step-by-step says:
URL encode the consumer key and the consumer secret according to RFC
1738. Note that at the time of writing, this will not actually change the consumer key and secret, but this step should still be performed
in case the format of those values changes in the future.
Concatenate the encoded consumer key, a colon character ":", and the
encoded consumer secret into a single string.
Base64 encode the string from the previous step.
And my code is:
require 'rest_client'
key = URI::encode('app_key')
secret = URI::encode('app_secret')
encoded = Base64.encode64("#{key}:#{secret}")
res = RestClient::Resource.new "https://api.twitter.com/oauth2/token/"
response = ''
options = {}
options['Authorization'] = "Basic #{encoded}"
options['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
res.post('grant_type=client_credentials', options) do |response, request, result|
response << "#{CGI::escapeHTML(response.inspect)}<br /><br />"
response << "#{CGI::escapeHTML(request.inspect)}<br /><br />"
response << "#{CGI::escapeHTML(result.inspect)}<br />"
end
render :text => txt
And I print out this:
"{\"errors\":[{\"label\":\"authenticity_token_error\",\"code\":99,\"message\":\"Unable to verify your credentials\"}]}"
#<RestClient::Request:0x9ece5d8 #method=:post, #headers={"Authorization"=>"Basic bXlfa2V5Om15X3NlY3JldA==\n", "Content-Type"=>"application/x-www-form-urlencoded;charset=UTF-8"}, #url="https://api.twitter.com/oauth2/token/", #cookies={}, #payload="", #user=nil, #password=nil, #timeout=nil, #open_timeout=nil, #block_response=nil, #raw_response=false, #verify_ssl=false, #ssl_client_cert=nil, #ssl_client_key=nil, #ssl_ca_file=nil, #tf=nil, #max_redirects=10, #processed_headers={"Accept"=>"*/*; q=0.5, application/xml", "Accept-Encoding"=>"gzip, deflate", "Authorization"=>"Basic bXlfa2V5Om15X3NlY3JldA==\n", "Content-Type"=>"application/x-www-form-urlencoded;charset=UTF-8", "Content-Length"=>"29"}, #args={:method=>:post, :url=>"https://api.twitter.com/oauth2/token/", :payload=>"grant_type=client_credentials", :headers=>{"Authorization"=>"Basic bXlfa2V5Om15X3NlY3JldA==\n", "Content-Type"=>"application/x-www-form-urlencoded;charset=UTF-8"}}>
#<Net::HTTPForbidden 403 Forbidden readbody=true>
My key and secret are valid.
Am I missing something?
Thanks!
EDIT:
Updating with the solution I've found.
The problem was on the Base64 convertion and string encoding.
I had to add a forced encoding parameter to the key+secret combination, for UTF-8 convertion:
encoded = Base64.encode64("#{key}:#{secret}".force_encoding('UTF-8'))
The Rails Base64.encode64 inserts a line break every 60 encoded characters.
The workaround was:
For Ruby 1.9+ (strict_ was included in Ruby 1.9)
Base64.strict_encode64(string)
For Ruby 1.9-
Base64.encode64(string).gsub('/\n/') # To remove the line break
Are you trying to implement Authorization with Tweeter (as OAuth Provider). Instead of writing it from the scratch following the API documentation, I would suggest to use OmniAuth. The setup & boilerplate code is fairly easy to use.
Read more about it at http://www.omniauth.org/ & https://github.com/intridea/omniauth/wiki
Let us know, if that helped you or not.

Trouble handling HTTP responses and parsing JSON data

I am using Ruby on Rails 3 and I would like to solve an issue with the following code where a web client application receive back some JSON data from a web service application that uses a Rack middleware in order to respond.
In the web client app model I have
response_parsed = JSON.parse(response.body)
if response_parsed["account"]
...
else
return response
end
In the above code the response.body come back from the web service app that uses a Rack middleware to respond to the web client:
accounts = Account.where(:id => ids)
[200, {'Content-Type' => 'application/json'}, accounts.to_json] # That is, response.body = accounts.to_json
Data transmission is ok, but I get the following error
TypeError
can't convert String into Integer
*Application Trace*
lib/accounts.rb:107:in `[]'
The line 107 corresponds to
if response_parsed["account"]
...
Where and what is the problem? How to solve that?
If I try to debug the respons.body I get
# Note: this is an array!
"[{\"account\":{\"firstname\":\"Semio\",\"lastname\":\"Iaven\"\"}}]"
If I'm saying something you already realize, forgive me.
It looks like your response is a one-element array with a hash in it as the first element. Because the response is an array, when you use the [] it is expecting a integer representing the index of the item in the array you'd like to access, and that is what the error message means--it expected that you'd tell it the integer value of the item you wanted, but instead you gave it a string.
If you instead do:
response_parsed[0]['account']
It seems like you'd get what you want.

Resources