My iOS developer was asking me to provide all timestamps in a JSON structure to be Unix timestamps, as the number of seconds that have elapsed since "00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970", not counting leap seconds.
Seeing that all of my data was stored in strings on the server, I would like to create a method to convert all of the timestamps to Unix timestamps as an integer.
In other words, I need to convert:
{
"created_at" => "2015-01-18T00:58:58.903Z",
"updated_at" => "2015-01-18T00:58:58.903Z",
"user_id" => 1,
"status_id" => 1
}
to:
{
"created_at" => 1421542604,
"updated_at" => 1421542604,
"user_id" => 1,
"status_id" => 1
}
I wrote the following rspec, then realized I need to modify the default as_json method to perform this conversion:
expect(response_json).to eq(
{
'created_at' => user.created_at.as_json,
'updated_at' => user.updated_at.as_json,
'user_id' => user.user_id,
'status_id' => user.status_id
}
)
I then created /config/initializers/unix_timestamps.rb and it worked:
class ActiveSupport::TimeWithZone
def as_json
self.to_time.to_i
end
end
Related
I have a scheduleevent model. The model uses ice_cube to create recurrence rules. A scheduleevent has_many schedtimeranges. A schedtimnerange has a start_time, end_time and booleans for the days of the week Sunday - Saturday. Whatever days are checked are true.
What I need to do is get those days in an array to pass them into ice_cube. How would I join scheduleevent to schedtimeranges, and get Sunday - Saturday where the value is true in a rails model? Do I query the records in the controller, then loop them in the model, or if I need to loop in the model, query them from the model?
Trying to do something like this, but getting a no method schedtimeranges error:
def self.timeranges
Schedtimeranges.where(scheduleevent_id: self.id).columns.select{ |c| c.type == :boolean }.map(&:name)
end
weekdays = self.timeranges
Scheduleevent Model:
has_many :schedtimeranges, inverse_of: :scheduleevent
accepts_nested_attributes_for :schedtimeranges, allow_destroy: true
EDIT:
weekdays = schedtimeranges.where(scheduleevent_id: id).columns.select{ |c| c.type == :boolean }.map(&:name).to_a
This works, but I just need to only get them where the value is true. How do I add that to this? So if a scheduleevent has say 3 schedtimeranges, I want to get the days of week, and start_time/end_time where they are true.
Expected output would be 07:00 AM, 14:00 PM, Monday, Thursday, Friday. (If those are the 3 days that are true.
create_table "schedtimeranges", force: :cascade do |t|
t.bigint "scheduleevent_id", null: false
t.string "start_time"
t.string "end_time"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "monday"
t.boolean "tuesday"
t.boolean "wednesday"
t.boolean "thursday"
t.boolean "friday"
t.boolean "saturday"
t.boolean "sunday"
t.index ["scheduleevent_id"], name: "index_schedtimeranges_on_scheduleevent_id"
end
EDIT 2:
This is how I am trying to create the recurrence rules. How would I loop the to_ice_cube and pass the scheduleevent_id through?
schedule = IceCube::Schedule.new(start)
case orule
when 'daily'
schedule.add_recurrence_rule IceCube::Rule.daily(1).until(end_date.to_time)
when 'weekly'
self.map(&:to_ice_cube).where(scheduleevent_id: self.id).each do |days|
schedule.add_recurrence_rule IceCube::Rule.weekly(1).day(days.map{|s| s.to_sym}).until(end_date.to_time)
end
end
The idea being that if it is a daily repeat type I just have a start time and end time between all days froms tart date to end date. If it is a weekly recurrence I want to create the rules for the times on those particular days.
I am getting an undefined method map the scheduleevent record.
I think you made it sound way more complicated than it is. Expected output helped a lot. I've added a couple of methods to Schedtimerange to make it simpler:
# why not ScheduleTimeRange and ScheduleEvent
class Schedtimerange < ApplicationRecord
# sometimes you just have to type all the attributes that you need
def days
{
monday: monday,
tuesday: tuesday,
wednesday: wednesday,
thursday: thursday,
friday: friday,
saturday: saturday,
sunday: sunday
}
end
# # or like this
# DAYS = %w[monday tuesday wednesday thursday friday saturday sunday].freeze
# def days
# attributes.slice(*DAYS)
# end
# desired format goes here
def to_ice_cube
[start_time, end_time, *days.compact_blank.keys]
end
end
https://api.rubyonrails.org/classes/Hash.html#method-i-compact_blank-21
>> Schedtimerange.first.to_ice_cube
=> ["07:00 AM", "08:00 AM", :monday, :friday]
>> Schedtimerange.where(scheduleevent_id: 1).map(&:to_ice_cube)
=> [["07:00 AM", "08:00 AM", :monday, :friday], ["11:00 AM", "04:00 PM", :monday, :tuesday]]
Do the same for Scheduleevent if you want:
class Scheduleevent < ApplicationRecord
has_many :schedtimeranges
def to_ice_cube
[id, schedtimeranges.map(&:to_ice_cube)]
end
end
>> Scheduleevent.limit(2).map(&:to_ice_cube)
=> [[1, [["07:00 AM", "08:00 AM", :monday, :friday], ["11:00 AM", "04:00 PM", :monday, :tuesday]]],
[2, [[nil, nil, :monday, :tuesday], [nil, nil, :tuesday, :wednesday]]]]
If you're calling it from Scheduleevent, just use association to get relevant ranges:
schedtimeranges.map(&:to_ice_cube).each do |days|
schedule.add_recurrence_rule IceCube::Rule.weekly(1).day(days).until(end_date.to_time)
end
I'm trying to change a 'time' entry with the date entered in the 'date' entry. So if the time is "2000-01-01 10:00:00 UTC" and the date is "2021-10-10" I want the output to be "2021-10-10 10:00:00 UTC".
I almost have it working, however; when I assign the updated date back to the original object, it does not save the change. For instance, in the code below, event_time contains the proper time I want, however, assigning it to #event.time and then printing #event.time shows the change did not take place.
def create
#event = Event.new(event_params)
event_date = #event.date
event_time = #event.time.change(:year => event_date.year, :month => event_date.month, :day => event_date.day)
puts event_time # prints 2021-10-22 06:06:00 UTC
#event.time = event_time
puts #event.time # prints 2000-01-01 06:06:00 UTC
if #event.save
redirect_to(events_path)
else
render('new')
end
end
Any suggestions? I'm new to Ruby so I'm probably missing something obvious here
Here's my schema
create_table "events", force: :cascade do |t|
t.date "date"
t.string "description"
t.boolean "isMandatory"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "name"
t.time "time"
t.string "location"
end
You can refer to the SO answer here
The problem is that there is no time-of-day class in Ruby or Rails. All the time classes are dates or timestamps (i.e. date plus time of day).
Inside the database it will be a time (without timezone) column and it will behave properly inside the database. However, once the time gets into Ruby, ActiveRecord will add a date component because there is no plain time-of-day class available, it just happens to use 2000-01-01 as the date.
Everything will be fine inside the database but you'll have to exercise a little bit of caution to ignore the date component when you're outside the database in Rails.
Use datetime column type to hold a date and time. Only use time in the migration if you don't need the date (only want to store time part).
I have a table called google_records in which every row is a snapshot of a google adwords account for that day.
Here is the schema -
create_table "google_records", :force => true do |t|
t.string "user_id"
t.string "date"
t.text "stats"
t.text "account_name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.decimal "total_cost", :precision => 12, :scale => 2, :default => 0.0, :null => false
t.integer "total_conversions", :default => 0, :null => false
end
add_index "google_records", ["date"], :name => "index_google_records_on_date"
stats contains a hash of the day's stats by campaign and an entry would look something like this:
:Carpet Cleaning:
:conversions: 3
:cost: 391.47
:Upholstery Cleaning:
:conversions: 0
:cost: 69.96
:Air Duct Cleaning:
:conversions: 0
:cost: 8.68
I just added those total_cost and total_conversion columns and I'd like to update those with the totals for each respective value each day.
I can get the total I want to work in my console like so(the cost total doesn't match up with the sample I gave but its only because I shortened the sample to fit better - the total is correct) -
user = User.find(6)
GoogleRecord.where(user_id: user).where(date: "20140328").map {|m| m.stats}.map{ |s| s.map{ |key, value| value[:cost] || 0 } }.map {|m| m.inject(:+)}.compact.reduce(&:+)
=> 660.26
I'd like to update all records in the table this way for conversions and cost and save them but when I try something like:
GoogleRecord.all.each do |g|
g.map {|m| m.stats}.map{ |s| s.map{ |key, value| value[:cost] || 0 } }.map {|m| m.inject(:+)}.compact.reduce(&:+)
end
I keep getting NoMethodError: undefined method map for GoogleRecord:0x5f09868
It seems like since I'm just grabbing one record in the example that is working, I should be able to apply code to each record.
Inside your example code, what the where method return is something like array, so map can work. But inside the GoogleRecord.all.each block, the g is reference to the db record. Remove the first map call, and see whether it will work.
GoogleRecord.all.each do |g|
g.stats.map{ |s| s.map{ |key, value| value[:cost] || 0 } }.map {|m| m.inject(:+)}.compact.reduce(&:+)
end
I have an error while trying to compare datetimes with rails and postgresql
Now, I created the table using this simple schema:
def change
create_table :events do |t|
t.string :name
t.datetime :start_time
end
end
I try then to get events in the future using this scope:
scope :active_events, ->(id) { includes(:event).where(:foursquare_id => id).where('events.start_time => now()::timestamp') }
That translate in postgresql as :
SELECT COUNT(DISTINCT "venues"."id")
FROM "venues"
LEFT OUTER JOIN "events" ON "events"."venue_id" = "venues"."id"
WHERE "venues"."foursquare_id" = '4ada1e5ff964a5209f1e21e3'
AND (events.start_time => now()::timestamp)
Now I have this error that shows up then :
PG::UndefinedFunction: ERROR: operator does not exist: timestamp without time zone => timestamp without time zone
LINE 1: ...'4ada1e5ff964a5209f1e21e3' AND (events.start_time => now()::...
and I'm really not sure to understand this. Normally they are of the same data type I assume they would be able to compare but it doesn't seem to be the case.
What am I missing here ?
The operator you're looking for is >=, => is usually used with hstore.
HI
whats the best way to implement a simple search in rails to retrieve all models with the same date?
e.g retrieve all customer with birthday date on 23-10-1975, which will be of a date format.
i.e
create_table "customer", :force => true do |t|
t.string "f_name"
t.string "m_name"
t.string "l_name"
t.date "date_of_birth"
end
I presume you want to congratulate all users that have their birthday today?
Well, I'm not on a dev-machine now, so I can't test it, but I would go for something like this:
#bday_customers = Customer.find(:all, :conditions => { :birthday => Date.today } )
or even
#bday_customers = Customer.find(:all, :conditions => { :birthday => (Date.today)..(Date.today + 2.weeks) } )
This will cause your database to do the work as it its optimised for such searches.
Assuming date is a string of the form 23-10-1975 then something like this;
Customer.all(:conditions => { :date_of_birth => Date.strptime(date, '%d-%m-%Y') })