Problems with parse while encoding ascii string - ruby

I'm trying to encode a string VULGO PIVETÃO, but i'm getting an error URI must be ascii only "https://127.0.0.1:2999/liveclientdata/playerscores?summonerName=VULGO PIVET\\u00C3O" (URI::InvalidURIError). I have tried the following block:
URI = "https://127.0.0.1:2999"
ENDPOINTS = {
allgamedata: "liveclientdata/allgamedata",
activeplayer: "liveclientdata/activeplayer",
playerlist: "liveclientdata/playerlist",
eventdata: "liveclientdata/eventdata",
playerscore: "liveclientdata/playerscores"
}
def get_playerscore summoner_name
summoner_name = "VULGO PIVETÃO"
begin
encoded_string = URI.parse(summoner_name)
rescue URI::InvalidURIError
encoded_string = URI.parse(URI.escape(summoner_name))
end
JSON.parse(Utils.req("GET","#{URI}/#{ENDPOINTS[:playerscore]}?summonerName=#{encoded_string}", {}, false))
end
But i'm still getting another error: rescue in get_playerscore': "https://127.0.0.1:2999" is not a class/module (TypeError)
SOLVED
According to #mu is too short suggestion, using the library: Addressable, I solved the problem with this block of code:
uri = "#{URI}/#{ENDPOINTS[:playerscore]}?summonerName=#{summoner_name}"
uri = Addressable::URI.parse(uri)
uri = uri.normalize
JSON.parse(Utils.req("GET", uri, {}, false))

Related

No implicit converson from nil to String

I am getting an error
ruby/2.1.0/open-uri.rb:36:in `open': no implicit conversion of nil into String (TypeError)
here #filename, #directory and #xmlFile all have String as class type if I print them.
But somehow still in eval_script the above error is thrown. I don't undertstand why?
def execute
...
#result = eval_script(#filename,#xmlFile,#directory)
end
def eval_script filename,xml,directory
proc = Proc.new{}
eval(File.read(filename),proc.binding, filename)
end
Edit:
1) execute method is my rails action controller method.
Script:
# encoding: UTF-8
require 'nokogiri'
require 'open-uri'
doc = Nokogiri::XML(open(ARGV.first))
path = ARGV[1]
print path
File.delete(path + "/testOut.txt") if File.exist?(path + "/testOut.txt")
file = File.open(path + "/testOut.txt", 'w')
doc.css('testcases').each { |node| file.write "#{node['name']}\n" if node.css('results[test="testOut"]').any? }
Well, there's your problem. Line 4 of your script is
doc = Nokogiri::XML(open(ARGV.first))
But there are no ARGV elements being passed, so you're trying to open nil
Since you have the binding available, just refer to the variables defined in the eval_script method.
doc = Nokogiri::XML(open(xml))

no implicit conversion of String into Integer (TypeError)

I am trying to parse a line of JSON using ruby and running into this error
no implicit conversion of String into Integer (TypeError)
uri = URI.parse('xxx')
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
if response.code == "200"
result = JSON.parse(response.body)
result.each do |doc|
#if doc.is_a?(Hash)
dns_name = doc['dns_name'] #reference properties like this <-- Line 25 (see below)
host = ['host']# this is the result in object form
#end
end
else
puts "ERROR!!!"
end
puts host
puts dns_name
I have looked at several similar questions but they didn't seem to help and I have tried changing
result.each do |doc|
to
result.each.first do |doc|
as discussed in them.
My ruby is passable at best but I would take a link to some docs as well, I have tried the official docs without much luck at this point. Here is what is returned:
[{"name":"server","power_state":"On","host":"host","cluster":"cluster","ip_address":"10.0.0.0","dns_name":"server.com","vcenter":"vcenter","description":" ","datastore":"datastore","num_vcpu":"2","mem_size_gb":8,"vmid":"1","application":"Misc","business_unit":"","category":"","support_contact":"joe#example.com"},200]
I have also tried .is_a?(Hash) and .is_a?(Array). I am fairly certain when I look at the json it is an array of hashes and the problem lies in the 200 response code I am getting back at the end of the line. Why that is a problem I have no idea, I would like to work around it but the json is generated by a known source so I may be able to have them modify it if I can show that it is faulty.
Thanks
UPDATE
As asked the full out from the error
'./status.rb:25:in `[]''
'./status.rb:25:in `block in ''
'./status.rb:23:in `each''
'./status.rb:23:in `''
In your case it doesn't really seem like their is a reason for the loop, you could just write:
dns_name = result.first['dns_name']
host = result.first['host']
Since result is an array with 2 objects 0 being the Hash and 1 being an Int that should work.
If you well-format the JSON it will look like this:
[
{
"name":"server",
"power_state":"On",
"host":"host",
"cluster":"cluster",
"ip_address":"10.0.0.0",
"dns_name":"server.com",
"vcenter":"vcenter",
"description":" ",
"datastore":"datastore",
"num_vcpu":"2",
"mem_size_gb":8,
"vmid":"1",
"application":"Misc",
"business_unit":"",
"category":"",
"support_contact":"joe#example.com"
},
200
]
You want to access the hash, it's the first element in the array so:
if response.code == "200"
result = JSON.parse(response.body)
dns_name = result.first['dns_name']
host = result.first['host']
else
puts "ERROR!!!"
end
No need for an each.

How do I POST XML using Faraday and receive response?

I am attempting to learn Ruby/Faraday. I need to POST XML to a RESTful web service and am confused on how to do this.
I have a string containing the XML as follows:
require "faraday"
require "faraday_middleware"
mystring = %&<xml><auth><user userid='username' pwd='password'/></auth></xml>&
How do I post the XML to a URL and receive the result? I am trying to do something like:
conn = Faraday.new(:url=>'http://url')
conn.post '/logon' {mystring}
I get the message:
SyntaxError: (irb):11: syntax error, unexpected '{', expecting $end
conn.post '/logon' {mystring}
Edit 1
I have gotten the POST request to work. My code is provided below.
require "faraday"
require "faraday_middleware"
myString = %&<xml><auth><user userid='username' pwd='password'/></auth></xml>&
myUrl = %&url&
conn = Faraday.new(:url => myUrl) do |builder|
builder.response :logger #logging stuff
builder.use Faraday::Adapter::NetHttp #default adapter for Net::HTTP
end
res = conn.post do |request|
request.url myUrl
request.body = myString
end
puts res.body
According to the documentation:
conn = Faraday.new(:url=>'http://url')
conn.post '/logon', mystring
There are two errors in your code. The first one is that you are missing a comma between the URL and the variable causing { mystring } to be interpreted as a block.
The second error is that mystring already holds a string and the following code does not make sense in Ruby:
{ "string" }
Thus conn.post '/logon', mystring is wrong. So the final result is:
conn = Faraday.new(:url=>'http://url')
conn.post '/logon', mystring
or:
conn = Faraday.new(:url=>'http://url')
conn.post '/logon', { :key => mystring }
if you want to submit a key/value POST body. But this is not your case, because you are already posting an XML body.

Ruby: Method doesn't run outside file where defined - "can't convert Symbol into Integer (TypeError)"

I'm a ruby newbie and this is my first (command-line for now) program.
First, some source.
file: AccessDb.rb
require 'mongo'
require 'json'
(...)
class AccessDb
def initialize dbname, collection #, username, password
#dbname = dbname
#collection = collection
#conn = Mongo::Connection.new
#db = #conn[dbname]
#coll = #db[collection]
end
def upsert_by_meta json
# print json
#coll.update({ :hash_md5 => json[:hash_md5] }, json, :upsert => true)
end
end
using
file: Downloader.rb
require 'curb'
require 'yaml'
require 'json'
(...)
class Downloader
def initialize(directory)
#PASS=nil
#COOKIE=nil
#filename=nil
#full_file_location = nil
#target_dir = directory
File.exists? #target_dir # File.directory? #target_dir
#c = Curl::Easy.new
curl_setup
#mongo = AccessDb.new "meta","meta"
end
def parse_link_info(url)
json = {}
json[:link_requested] = url
if #c.last_effective_url != url
then json[:link_final] = #c.last_effective_url end
json[:link_filename_requested] = #filename
#final_filename = #c.last_effective_url.split(/\?/).first.split(/\//).last
if #final_filename != #filename
then json[:link_filename_delivered] = #final_filename end
json[:link_filetime] = Time.at(#c.file_time).utc.to_s
json[:content_lenght] = #c.downloaded_content_length
json[:content_type] = #c.content_type
#hash = MovieHasher::compute_hash(#save_location)
#hash = MovieHasher::compute_hash(#save_location)
if !#hash.nil?
then json[:hash_bigfile] = #hash end
json[:hash_md5] = Digest::MD5.hexdigest(File.read(#save_location))
JSON.pretty_generate(json)
end
(json is some generated json file)
using code from Downloader.rb in the AccessDb.rb tests works perfectly, but when the method is used in Downloader.rb I get the following output:
D:/Dropbox/#code/PracaInz-Program/AccessDb.rb:20:in `[]': can't convert Symbol into Integer (TypeError)
from D:/Dropbox/#code/PracaInz-Program/AccessDb.rb:20:in `upsert_by_meta'
from D:/Dropbox/#code/PracaInz-Program/Downloader.rbw:158:in `block in add_links'
from D:/Dropbox/#code/PracaInz-Program/Downloader.rbw:148:in `each'
from D:/Dropbox/#code/PracaInz-Program/Downloader.rbw:148:in `add_links'
from D:/Dropbox/#code/PracaInz-Program/Downloader.rbw:189:in `<main>'
[Finished in 4.9s with exit code 1]
in a method code that perfectly works tested inside one file.. How can I write it so it can use symbols but works outside that specific file. Thx
def parse_link_info(url)
json = {}
json[:link_requested] = url
if #c.last_effective_url != url
then json[:link_final] = #c.last_effective_url end
json[:link_filename_requested] = #filename
#final_filename = #c.last_effective_url.split(/\?/).first.split(/\//).last
if #final_filename != #filename
then json[:link_filename_delivered] = #final_filename end
json[:link_filetime] = Time.at(#c.file_time).utc.to_s
json[:content_lenght] = #c.downloaded_content_length
json[:content_type] = #c.content_type
#hash = MovieHasher::compute_hash(#save_location)
#hash = MovieHasher::compute_hash(#save_location)
if !#hash.nil?
then json[:hash_bigfile] = #hash end
json[:hash_md5] = Digest::MD5.hexdigest(File.read(#save_location))
JSON.pretty_generate(json)
end
def add_links(url_array,cred=nil,ref=nil,cookie=nil)
link_setup(cred,ref,cookie)
url_array.each do |single_url|
#c.url=single_url
#filename = single_url.split(/\?/).first.split(/\//).last
#save_location = #target_dir + '\\' + #filename
# puts #save_location
#c.perform
File.open(#save_location,"wb").write #c.body_str
json = parse_link_info single_url
# puts json
id = #mongo.upsert_by_meta json
puts id
json["_id"] = id
File.open(#save_location + :"meta.json","w").write json
end
end
EDIT: more code (json definition), full trace
parse_link_info returns JSON.pretty_generate(json), i.e a string.
You pass the result of that into upsert_by_meta as its json parameter, which tries to access it as a hash (you do json[:hash_md5]) which you can't do with a string. String's [] method expects you to pass an integer (or a pair of integers) hence the method about not being able to convert the symbol to an integer
Looks like the code you have shown would work if parse_link_info just returned your json object rather than calling JSON.pretty_generate

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