RoR - Time.strptime issues - ruby-on-rails

Here is the method in question.
def published_at_setter
self.published_at = Time.strptime("#{#date} #{#time}", "%m/%d/%Y %I:%M %p")
puts " ~~~~~~~~~~~~~~~~~~~ #{#date} #{#time} ~~~~~~~~~~~~~~~~ #{self.published_at}"
end
With #date = "09/11/2012" and #time "01:45 AM" I get this in the webbrick console. WFT?
~~~~~~~~~~~~~~~~~~~ 09/11/2012 01:45 AM ~~~~~~~~~~~~~~~~ 2012-09-11 06:45:00 UTC
When in rails console I get the expected results. "2012-09-11 01:45:00 -0500"

Instead of Time.strptime, you should use Time.zone.parse.
def published_at_setter
self.published_at = Time.zone.parse("#{#date} #{#time}")
puts " ~~~~~~~~~~~~~~~~~~~ #{#date} #{#time} ~~~~~~~~~~~~~~~~ #{self.published_at}"
end

Related

Can't loop through JSON data because of the error "no implicit conversion of hash into integer"

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)

Given a start and end date, how can I loop until I reach the end date?

I have a start_dt and an end_dt object that are of type datetime.
How can I loop from the start_dt, incrementing by 1 day each time until I reach the end date?
You can use the upto and downto methods on Date and DateTime objects:
start_dt = DateTime.parse('2018-01-01')
end_dt = DateTime.parse('2018-01-15')
start_dt.upto(end_dt) { |date| puts date }
2018-01-01T00:00:00+00:00
2018-01-02T00:00:00+00:00
2018-01-03T00:00:00+00:00
2018-01-04T00:00:00+00:00
2018-01-05T00:00:00+00:00
2018-01-06T00:00:00+00:00
2018-01-07T00:00:00+00:00
2018-01-08T00:00:00+00:00
2018-01-09T00:00:00+00:00
2018-01-10T00:00:00+00:00
2018-01-11T00:00:00+00:00
2018-01-12T00:00:00+00:00
2018-01-13T00:00:00+00:00
2018-01-14T00:00:00+00:00
2018-01-15T00:00:00+00:00
end_dt.downto(start_dt) { |date| puts date }
2018-01-15T00:00:00+00:00
2018-01-14T00:00:00+00:00
2018-01-13T00:00:00+00:00
2018-01-12T00:00:00+00:00
2018-01-11T00:00:00+00:00
2018-01-10T00:00:00+00:00
2018-01-09T00:00:00+00:00
2018-01-08T00:00:00+00:00
2018-01-07T00:00:00+00:00
2018-01-06T00:00:00+00:00
2018-01-05T00:00:00+00:00
2018-01-04T00:00:00+00:00
2018-01-03T00:00:00+00:00
2018-01-02T00:00:00+00:00
2018-01-01T00:00:00+00:00
How about this?
current_date = object.start_dt
end_date = object.end_dt
loop do
## do something
## (`:beginning_of_day` and `:end_of_day` may help you)
current_date += 1.day
break if current_date > end_date
end
Try to the following
start_date = Time.now - 30.day
=> 2017-12-16 09:19:51 +gmt
end_date = Time.now
=> 2018-01-15 09:19:44 +gmt
start_date = Date.parse "#{start_date}"
end_date = Date.parse "#{end_date}"
date_count = (end_date - start_date).to_i
=> 30
<% (1..date_count).each do |i| %>
#Code to display using <%= i %> that you want to display
<% end %>
Hope to help
Try these:
(DateTime.parse('2018-01-01')..DateTime.parse('2018-01-15')).each do |date|
puts date
end

Ruby: Sort Dates by their closeness to some test date

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 }

How to use Ruby's send method without receiver?

I am trying to convert user input à la "6 months" into a Ruby method à la 6.months.
How can this be done?
I keep getting an undefined method 6.months error in line 10.
Thanks for any help.
class Coupon < ActiveRecord::Base
def self.duration_options
["3 years", "2 years", "1 year", "6 months", "3 months", "1 month"]
end
def end_at
if Coupon.duration_options.include?(duration)
method = duration.sub!(' ', '.')
time = Time.zone.now + send(method)
end
time
end
end
Your send is on the object itself, in this case it's self.send(method)
You could do like this
if Coupon.duration_options.include?(duration)
off_set = duration.split(" ")
time = Time.zone.now + off_set.first.to_i.send(off_set.last.to_sym)
end
time

Argument error : invalid date

What this error could be about? I'm defining an age at my account model:
def age
birthday = DateTime.new(year_Of_Birth.to_i, month_Of_Birth.to_i, day_Of_Birth.to_i)
self.age = ((DateTime.now - birthday) / 365.25).to_i
end
and in my view i get the following error:
ArgumentError - invalid date in the following line:
<dd><%= #account.age %></dd>
Thanks in advance.
Try to test in your Rails app console:
birthday = DateTime.new(1991,4,2) => Tue, 02 Apr 1991 00:00:00 +0000
DateTime.now - birthday => (149073456141953/17280000000)
(DateTime.now - birthday)/365.25 => 23.61926437561592
((DateTime.now - birtday)/365.25).to_i => 23
This works for me. Check the params that you're setting.
I'm almost sure the arguments that you're passing (year_Of_Birth.to_i, month_Of_Birth.to_i, day_Of_Birth.to_i) have something wrong, debug them and show us the values, or if you want you can try this to catch some specific error:
begin
birthday = DateTime.new(year_Of_Birth.to_i, month_Of_Birth.to_i, day_Of_Birth.to_i)
self.age = ((DateTime.now - birthday) / 365.25).to_i
rescue ArgumentError
#your logic
end

Resources