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)
I have an array of dates. I need to sort those dates by their closeness to some test_date. The dates in the array can be before or after that test_date.
My simple ruby program isn't getting it right. My strategy is to convert each Date to a unix timestamp. Then I do a custom sort by the absolute value of the difference between the dates and the test_date.
Here is that program:
require 'date'
test_date = DateTime.new(2017,2,3,4,5,6)
date1 = Date.new(2017,1,6)
date2 = Date.new(2017,1,5)
date3 = Date.new(2017,2,5)
date4 = Date.new(2017,2,6)
date5 = Date.new(2017,2,9)
date6 = Date.new(2017,2,1)
date7 = Date.new(2017,2,2)
dates_ary = date1, date2, date3, date4, date5, date6, date7
sorted_dates = dates_ary.sort do |d1, d2|
if( (d1.to_time.to_i - test_date.to_time.to_i).abs <= (d2.to_time.to_i - test_date.to_time.to_i).abs)
d1 <=> d2
else
d2 <=> d1
end
end
puts "expected order: "
puts "2017-02-02"
# pointed out in comments that 2017-02-05 will be closer than 2017-02-01 due to test_date having present hours, minutes, and seconds.
puts "2017-02-05"
puts "2017-02-01"
puts "2017-02-06"
puts "2017-02-09"
puts "2017-01-06"
puts "2017-01-05"
puts ''
puts 'actual order:'
sorted_dates.each {|d| puts d}
Also: if there is some existing ruby or rails method that sorts dates by their closeness to another date, let me know. Thanks!
The if is redundant. Ruby will handle it:
sorted_dates = dates.sort do |d1, d2|
(d1.to_time.to_i - test_date.to_time.to_i).abs <=> (d2.to_time.to_i - test_date.to_time.to_i).abs
end
Better:
sorted_dates = dates.sort_by do |date|
(date.to_time.to_i - test_date.to_time.to_i).abs
end
Better:
sorted_dates = dates.sort_by { |date| (date - test_date).abs }