Ruby Uninitialized constant error - ruby

I am using a dashing weather widget but it seems to be creating an error when I run the Ruby job file. The following is the Ruby file
require 'net/https'
require 'json'
# Forecast API Key from https://developer.forecast.io
forecast_api_key = ""
# Latitude, Longitude for location
forecast_location_lat = "45.429522"
forecast_location_long = "-75.689613"
# Unit Format
# "us" - U.S. Imperial
# "si" - International System of Units
# "uk" - SI w. windSpeed in mph
forecast_units = "si"
SCHEDULER.every '5m', :first_in => 0 do |job|
http = Net::HTTP.new("api.forecast.io", 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
response = http.request(Net::HTTP::Get.new("/forecast/#{forecast_api_key}/#{forecast_location_lat},#{forecast_location_long}?units=#{forecast_units}"))
forecast = JSON.parse(response.body)
forecast_current_temp = forecast["currently"]["temperature"].round
forecast_current_icon = forecast["currently"]["icon"]
forecast_current_desc = forecast["currently"]["summary"]
if forecast["minutely"] # sometimes this is missing from the response. I don't know why
forecast_next_desc = forecast["minutely"]["summary"]
forecast_next_icon = forecast["minutely"]["icon"]
else
puts "Did not get minutely forecast data again"
forecast_next_desc = "No data"
forecast_next_icon = ""
end
forecast_later_desc = forecast["hourly"]["summary"]
forecast_later_icon = forecast["hourly"]["icon"]
send_event('forecast', { current_temp: "#{forecast_current_temp}°", current_icon: "#{forecast_current_icon}", current_desc: "#{forecast_current_desc}", next_icon: "#{forecast_next_icon}", next_desc: "#{forecast_next_desc}", later_icon: "#{forecast_later_icon}", later_desc: "#{forecast_later_desc}"})
end
and it gives the error /forecast.rb:3: invalid multibyte char (US-ASCII) (SyntaxError)
which is weird because line 3 is blank in the file.
So I decided to add # encoding: utf-8 at the beginning of the file to try to fix this but then I get the error uninitialized constant on line 4 (again a blank line). can someone help me out with this?
The complete error message was
/usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb:3: warning: method redefined; discarding old default_dir
/usr/lib/ruby/1.9.1/rubygems/defaults.rb:25: warning: previous definition of default_dir was here
/usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb:7: warning: method redefined; discarding old default_bindir
/usr/lib/ruby/1.9.1/rubygems/defaults.rb:96: warning: previous definition of default_bindir was here
/home/pi/xxxxx/jobs/forecast.rb:3: invalid multibyte char (US-ASCII)

I changed SCHEDULER to Dashing.scheduler and was able to get past this error.

Related

TypeError problem: no implicit conversion in Sinatra + JSON.parse

I'm trying to set up a web hook, following this GitHub tutorial
require 'sinatra'
require 'json'
require 'net/http'
require 'pp'
set :port, 31415
# Descarga las diferencias hechas para un push
post '/' do
push = JSON.parse(request.body.read)
piezas = push["compare"].split("/")
api_url = "/repos/#{piezas[3]}/#{piezas[4]}/compare/#{piezas[6]}"
diff = Net::HTTP.get(URI("https://api.github.com#{api_url}"))
puts diff.class
pp(JSON.parse(diff))
end
diff.class prints:
String
And, as a matter of fact, the last sentence works correctly, printing via pp the structure. However, after printing, it yields the error
[2018-10-25 20:00:23] ERROR TypeError: no implicit conversion of Array into String
It's not referencing any line in the script, but would it be possible that the error would be in the first JSON.parse? Could it be that request.body.read would be an array?
Update I couldn't golf it down to any of the JSON.parse separately. Downloading the hook payload works OK, downloading the JSON from the GitHub API works without a glithc. Somehow it's using them together what does not work.
It's possible the library is treating the response like text. Try adding an Accept header. This worked for me:
request["Accept"] = "application/json"
example:
uri = URI.parse("https://api.github.com")
req = Net::HTTP::Get.new(URI("https://api.github.com/repos/JJ/microservices-broker/compare/d5d39c5db99d...bbbf695d1bf2"))
req["Accept"] = 'application/json'
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
response = http.request(req)
json = JSON.parse(response.body)
json['url']
# or
json = JSON.parse(response.body, symbolize_names: true)
json[:url]
(EDIT:) Also, Using Net::HTTP is really painful. Please checkout these libraries:
https://github.com/lostisland/faraday
https://github.com/octokit/octokit.rb

How do I log a URL encode if it's a private method?

Using Ruby 1.9.1 or 1.9.3, I have a problem inserting the % symbol into a database.
The exception is:
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/uri/common.rb:898:in `decode_www_form_component'
I was told to use p to output str.
This is ruby/lib/1.9.1/util/common.rb:
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
require 'logger'
# Keep data for the current month only
$LOG = Logger.new('this_month.log', 'monthly')
$LOG.debug("#{str.p}")
raise ArgumentError, "invalid %-encoding (#{str})" unless /\A[^%]*(?:%\h\h[^%]*)*\z/ =~ str
str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
end
I got this error:
Internal Server Error
cannot parse Cookie header: private method `p' called for "innate.sid":String
How do I p str to find out what's inside it and maybe what encoding it is?
You don't need the p method if you're using logger. p and puts output to stdout.
# this is equavalent to `puts str`
$LOG.debug(str)
# for more "raw" data
# `p str` or `puts str.inspect`
$LOG.debug(str.inspect)

Error code in ruby

I'm looking for some help with my code...
# save text file to string
data = File.read("workdata.txt")
# split string into blocks of text relevant to each journey
journeys = data.split(/\n\s\n/)
# store the amount of journeys as a variable called journeys_size
journeys_size = journeys.length
# split each journey into lines and save to an array called "journey_lines"
#journey_lines = journeys.map { |i| i.split(/\n/) }
# cretae an array called "all_journey_objects" to hold all journeys
all_journey_objects = []
# step through the journey arrays
#journey_lines.each do |line|
next if line[0].include?("position") # skip the journey block of text if it contains position
destinations = []
destination1 = line[12].upcase
destination2 = line[13].scan(/[a-z]+/i).join(" ").upcase
# destination3 = line[14].scan(/[a-z]+/i).join(" ").upcase # <---- When i uncomment this line **
# destination4 = line[15].scan(/[a-z]+/i).join(" ").upcase
# destination5 = line[16].scan(/[a-z]+/i).join(" ").upcase
puts destination1
puts destination2
# puts destination3 # <---- When i uncomment this line **
# puts destination5
# puts destination4
# journey = Journey.new(line[0] , line[1] , line[6] , destinations, etas, windows)
# all_journey_objects << journey
end
The problem I am having is the following error when executed:
watcher.rb:47: in 'block in <main>': undefined method'scan' for nil:NilClass (NoMethodError)
I think the reason is because the "workdata.txt" file that I am working with, contains some journeys which only have two destinations. So, as soon as i uncomment the lines to create a third destination variable it throws an error. Maybe because it is trying to run a method against an object that doesn't exist?
I am stuck with finding a way around this. Any help would be appreciated...
If this is line 47:
destination3 = line[14].scan(/[a-z]+/i).join(" ").upcase
undefined method `scan' for nil:NilClass indicates that you are sending scan to nil. In other words, line[14] is nil.
You could simply add an if statement:
if line[14]
destination3 = line[14].scan(/[a-z]+/i).join(" ").upcase
end
Or an inline if:
destination3 = line[14].scan(/[a-z]+/i).join(" ").upcase if line[14]

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.

Ruby - Microsoft Translator unexpected token error

I'm using the following method to translate a simple word from English to Russian by calling:
translate("hello")
This is my method:
def translate(text)
begin
uri = "http://api.microsofttranslator.com/V2/Ajax.svc/GetTranslations?appId=#{#appid}&text=#{text.strip}&from=en&to=ru&maxTranslations=1"
page = HTTParty.get(uri).body
show_info = JSON.parse(page) # this line throws the error
rescue
puts $!
end
end
The JSON output:
{"From":"en","Translations":[{"Count":0,"MatchDegree":100,"MatchedOriginalText":"","Rating":5,"TranslatedText":"Привет"}]}
The error:
unexpected token at '{"From":"en","Translations":[{"Count":0,"MatchDegree":100,"MatchedOriginalText":"","Rating":5,"TranslatedText":"Привет"}]}'
Not sure what it means by unexpected token. It's the only error I'm receiving. Unfortunately I can't modify the JSON output as it's returned by the API itself.
UPDATE:
Looks like the API is returning some illegal characters (bad Microsoft):
'´╗┐{"From":"en","Translations":[{"Count":0,"MatchDegree":0,"Matched OriginalText":"","Rating":5,"TranslatedText":"Hello"}]}'
Full error:
C:/Ruby193/lib/ruby/1.9.1/json/common.rb:148:in `parse': 743: unexpected token at '´╗┐{"From":"en","Translations":[{"Count":0,"MatchDegree":0,"Matched
OriginalText":"","Rating":5,"TranslatedText":"Hello"}]}' (JSON::ParserError)
from C:/Ruby193/lib/ruby/1.9.1/json/common.rb:148:in `parse'
from trans.rb:13:in `translate'
from trans.rb:17:in `<main>'
Try ensuring UTF-8 encoding and stripping any leading BOM indicators in the string:
# encoding: UTF-8
# ^-- Make sure this is on the first line!
def translate(text)
begin
uri = "http://api.microsofttranslator.com/V2/Ajax.svc/GetTranslations?appId=#{#appid}&text=#{text.strip}&from=en&to=ru&maxTranslations=1"
page = HTTParty.get(uri).body
page.force_encoding("UTF-8").gsub!("\xEF\xBB\xBF", '')
show_info = JSON.parse(page) # this line throws the error
rescue
puts $!
end
end
Sources:
Ruby 1.9's String
Wikipedia: Byte order mark
Using awk to remove the Byte-order mark

Resources