I have a service method that makes api requests and if the response was not ok, it would notify Bugsnag. It looks like this:
def send_request
#response = HTTParty.get(api_endpoint, options)
return JSON.parse(#response.body, symbolize_names: true) if #response.ok?
raise StandardError.new(JSON.parse(#response.body))
rescue StandardError => exception
BugsnagService.notify(exception, #response)
end
My BugsnagService#notify looks something like this:
class BugsnagService
def self.notify(exception, response = nil, **options)
if response
response_body = if valid_json?(response.body) # Error right here
JSON.parse(response.body)
else
response.body
end
options[:response_body] = response_body
options[:response_code] = response.code
end
# Raising exception in test and development environment, or else the exception will be
# silently ignored.
raise exception if Rails.env.test? || Rails.env.development?
Bugsnag.notify(exception) do |report|
report.add_tab(:debug_info, options) if options.present?
end
end
def self.valid_json?(json_string)
JSON.parse(json_string)
true
rescue JSON::ParserError => e
false
end
end
I set response = nil in my notify method because not every error is an API error, so sometimes I would just call BugsnagService.notify(exception).
I found out that if I just call it like I am in the snippet above, it would raise an error saying it can't call .body on a Hash. Somehow, when I pass #response into BugsnagService#notify, the object turns from HTTParty::Response into Hash.
But if I pass something in for the **options parameter, it will work. So I can call it like this:
BugsnagService.notify(exception, #response, { })
I've been trying to figure this one out but I couldn't find anything that would explain this. I'm not sure if there's something wrong with the way I define my parameters or if this is some bug with the HTTParty gem. Can anyone see why this is happening? Thanks!
The problem is that your #response is being passed in as the options, as response can be nil. The double splat is converting it to a hash.
Try:
def testing(x, y = nil, **z)
puts "x = #{x}"
puts "y = #{y}"
puts "z = #{z}"
end
testing 1, 2, z: 3
#=> x = 1
#=> y = 2
#=> z = {:z=>3}
testing 1, y: 2
#=> x = 1
#=> y =
#=> z = {:y=>2}
testing 1, { y: 2 }, {}
#=> x = 1
#=> {:y=>2}
#=> {}
I'd suggest the best approach would be to have response be a keyword arg, as in:
def self.notify(exception, response: nil, **options)
...
end
That way, you can still omit or include the response as desired, and pass in subsequent options.
Hello and good afternoon all!
I am getting an error in my console that states "TypeError: No implicit conversion of hash into integer" and I know that it is referring to my loop in my Ruby class document.
Here is my Ruby file:
require 'HTTParty'
require 'pp'
require 'pry'
=begin
find a way to access the latitude and longitude of the nearest charging station globally
find a way to access the latitude and longitude of the user
create a function that finds the nearest station based on accepting both sets of coordinates and finds the difference
=end
class ChargingStations
include HTTParty
attr_accessor :pois
puts "loading"
##latitude = ''
base_uri 'https://api.openchargemap.io/v2'
def self.puts_latitude
puts ##latitude
end
def initialize(pois)
##pois = pois
##latitude = ##pois
puts ##pois
end
def self.put_value
puts ##latitude
end
def self.find_sites
for i in ##pois do
puts ##pois[i]
if ##pois[i]["AddressInfo"]["StateOrProvince"] == "New York"
puts ##pois[i]
end
end
end
def self.generate
response = get('/poi')
puts "got here"
if response.success?
puts "success"
self.new(response)
else
puts "failure"
raise response.response
end
end
end
binding.pry
If you are able to answer the question, please explain why my loop does not work for myself and future developers.
Thank you!
Why don't you give this a try:
class ChargingStations
include HTTParty
##latitude = ''
base_uri 'https://api.openchargemap.io/v2'
class << self
def pois
##pois
end
def puts_latitude
puts ##latitude
end
def put_value
puts ##latitude
end
def state_or_provinces
#state_or_provinces ||= ##pois.map do |poi|
poi.try(:[],'AddressInfo').try(:[],'StateOrProvince')
end.uniq
end
def find_sites(state_or_province=nil)
#state_or_province = state_or_province
#state_or_province ||= 'New York'
##pois.select do |poi|
poi.try(:[],'AddressInfo').try(:[],'StateOrProvince') == #state_or_province
end
end
def generate
response = get('/poi')
if response.success?
##pois = response.parsed_response
##latitude = ##pois
return true
else
puts "failure"
raise response.response
end
end
end # Class methods
end
Then, in console, I get:
ChargingStations.generate
=> true
ChargingStations.find_sites.count
=> 2
ChargingStations.find_sites.first
=> {"ID"=>112491, "UUID"=>"5EA5B030-AFEF-4CFA-88DF-3A9F6CFFDAB5", "ParentChargePointID"=>nil, "DataProviderID"=>1, "DataProvider"=>{"WebsiteURL"=>"http://openchargemap.org", "Comments"=>nil, "DataProviderStatusType"=>{"IsProviderEnabled"=>true, "ID"=>1, "Title"=>"Manual Data Entry"}, "IsRestrictedEdit"=>false, "IsOpenDataLicensed"=>true, "IsApprovedImport"=>true, "License"=>"Licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)", "DateLastImported"=>nil, "ID"=>1, "Title"=>"Open Charge Map Contributors"}, "DataProvidersReference"=>nil, "OperatorID"=>5, "OperatorInfo"=>{"WebsiteURL"=>"http://www.chargepoint.net/", "Comments"=>nil, "PhonePrimaryContact"=>"1-888-758-4389", "PhoneSecondaryContact"=>nil, "IsPrivateIndividual"=>false, "AddressInfo"=>nil, "BookingURL"=>nil, "ContactEmail"=>"support#coulombtech.com", "FaultReportEmail"=>"support#coulombtech.com", "IsRestrictedEdit"=>nil, "ID"=>5, "Title"=>"ChargePoint (Coulomb Technologies)"}, "OperatorsReference"=>nil, "UsageTypeID"=>1, "UsageType"=>{"IsPayAtLocation"=>nil, "IsMembershipRequired"=>nil, "IsAccessKeyRequired"=>nil, "ID"=>1, "Title"=>"Public"}, "UsageCost"=>"free", "AddressInfo"=>{"ID"=>112837, "Title"=>"1 Locks Plaza", "AddressLine1"=>"1 Locks Plaza", "AddressLine2"=>nil, "Town"=>"Lockport", "StateOrProvince"=>"New York", "Postcode"=>"14094", "CountryID"=>2, "Country"=>{"ISOCode"=>"US", "ContinentCode"=>"NA", "ID"=>2, "Title"=>"United States"}, "Latitude"=>43.169316400362, "Longitude"=>-78.6954369797903, "ContactTelephone1"=>nil, "ContactTelephone2"=>nil, "ContactEmail"=>nil, "AccessComments"=>"Located at the Lockport Municipal building, \"The Big Bridge\" and the \"Flight of Five\" locks 34 and 35 on the Erie Canal.", "RelatedURL"=>nil, "Distance"=>nil, "DistanceUnit"=>0}, "NumberOfPoints"=>1, "GeneralComments"=>"Located at the \"Big Bridge\" and \"Flight of Five\" locks 34 and 35 and the Lockport Municipal building", "DatePlanned"=>nil, "DateLastConfirmed"=>nil, "StatusTypeID"=>50, "StatusType"=>{"IsOperational"=>true, "IsUserSelectable"=>true, "ID"=>50, "Title"=>"Operational"}, "DateLastStatusUpdate"=>"2018-11-04T12:56:00Z", "DataQualityLevel"=>1, "DateCreated"=>"2018-11-04T05:18:00Z", "SubmissionStatusTypeID"=>200, "SubmissionStatus"=>{"IsLive"=>true, "ID"=>200, "Title"=>"Submission Published"}, "UserComments"=>[{"ID"=>20389, "ChargePointID"=>112491, "CommentTypeID"=>10, "CommentType"=>{"ID"=>10, "Title"=>"General Comment"}, "UserName"=>"Robert Seemueller", "Comment"=>"Located next to the Erie Canal's \"Flight of Five\" locks, downtown shops and restaurants.", "Rating"=>5, "RelatedURL"=>nil, "DateCreated"=>"2018-11-04T05:22:02.4Z", "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "CheckinStatusTypeID"=>10, "CheckinStatusType"=>{"IsPositive"=>true, "IsAutomatedCheckin"=>false, "ID"=>10, "Title"=>"Charged Successfully"}}], "PercentageSimilarity"=>nil, "Connections"=>[{"ID"=>158246, "ConnectionTypeID"=>1, "ConnectionType"=>{"FormalName"=>"SAE J1772-2009", "IsDiscontinued"=>nil, "IsObsolete"=>nil, "ID"=>1, "Title"=>"J1772"}, "Reference"=>nil, "StatusTypeID"=>50, "StatusType"=>{"IsOperational"=>true, "IsUserSelectable"=>true, "ID"=>50, "Title"=>"Operational"}, "LevelID"=>2, "Level"=>{"Comments"=>"Over 2 kW, usually non-domestic socket type", "IsFastChargeCapable"=>false, "ID"=>2, "Title"=>"Level 2 : Medium (Over 2kW)"}, "Amps"=>nil, "Voltage"=>nil, "PowerKW"=>nil, "CurrentTypeID"=>nil, "CurrentType"=>nil, "Quantity"=>2, "Comments"=>nil}], "MediaItems"=>[{"ID"=>16951, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405191125.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405191125.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:19:00Z"}, {"ID"=>16952, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405224211.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405224211.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:23:00Z"}, {"ID"=>16953, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405240797.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405240797.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:24:00Z"}], "MetadataValues"=>nil, "IsRecentlyVerified"=>true, "DateLastVerified"=>"2018-11-04T05:22:02.4Z"}
ChargingStations.find_sites('WA').count
=> 1
In general, when you use the construct for foo in fooArray to iterate over a Array, the foo is not the index but the actual item located in that position. So if you wanted your algorithm to work with minimal modifications, the "right" way would look like:
##pois.each_index do |i|
puts ##pois[i]
// rest of the algorithm ommited
end
In your case, assuming that the structure of your JSON data is something like [{lat: 10, lng: 10},{lat:5, lng:8}, {lat: 9, lng: -3], you are basically trying to do ##pois[{lat: 10, lng: 5}]], which will give you the exact "no implicit conversion" error that you're getting. You could just use i directly like puts i or i["AddressInfo"]["StateOrProvince"] and get the right answer.
However, as it has been mentioned in the comments, a more idiomatic approach would be ##pois.each do |poi|. And an even more idiomatic approach would be to rename that ugly-looking "pois" everywhere and make it
##positions.each do |position|
puts position
if position["AddressInfo"]["StateOrProvince"] == "New York"
puts position
end
end
Explicit variable names is the Ruby thing to do :)
And assuming the first puts is just a general test to see it's working and you actually want to only print the ones that are in New York...
##positions.each do |position|
puts position if position["AddressInfo"]["StateOrProvince"] == "New York"
end
And if you want to make that a one liner:
##positions.each { |pos| puts pos if pos["AddressInfo"]["StateOrProvince"] == "New York" }
(yeah, I know I just talked about explicit variable names but there is no need to be too rigid about it)