Reputation:
How do I set duration for my Product
object? So that, when a product is created by a user, it sets the JS counter to 1 day
and then destroys/inactivates the @product
when the clock runs out.
I know how to run this asynchronously, using Sidekiq. The thing is I don't know how to get ruby to work with my working client side JS countdown. And, how to tell Rails that every time a product is created it'd have a period of 1 day (perhaps a callback?).
def end_time
self.destroy in 1.days
self.update_attribute(:end_time, Time.now)
end
EDIT:
It throws an error for the view.
Illegal nesting: content can't be both given on the same line as %div and nested within it.
Here's the model.
#countdown{"data-created-at" => @product.created_at}
%digits
%span.days
%pcd DAYS
%digits
%span.hours
%pcd HRS
%digits
%span.minutes
%pcd MINS
%digits
%span.seconds
%pcd SECS
products.js
function getTimeRemaining(endtime){
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor( (t/1000) % 60 );
var minutes = Math.floor( (t/1000/60) % 60 );
var hours = Math.floor( (t/(1000*60*60)) % 24 );
var days = Math.floor( t/(1000*60*60*24) );
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime){
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock(){
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if(t.total<=0){
clearInterval(timeInterval);
}
}
updateClock();
var timeInterval = setInterval(updateClock,1000);
}
var deadline = 'December 15 2015 00:00:50 UTC+0200';
initializeClock('countdown', deadline);
Upvotes: 1
Views: 228
Reputation: 76774
Just to be clear, @product
won't exist after you close the browser - you're probably referring to a Product
object; which is a different matter.
If you wanted to create a Project
object, and have it time out after a day, you'd be able to use some sort of asynchronous cron system (I'll explain in a second).
However, you are asking something more pertinent:
The thing is I don't know how to get ruby to work with my working client side JS countdown
You just need to make sure you're able to bind the countdown with the@product.created_at
attribute:
#app/controllers/products_controller.rb
class ProductsController < ApplicationController
def show
@product = Product.find params[:id]
end
end
This will allow you to call:
#app/views/products/show.html.erb
<div id="countdown" data-created-at="<%= @product.created_at %>"> </div>
#app/assets/javascripts/application.js
function getTimeRemaining(endtime){
var t = Date.parse(endtime) - Date.now();
var seconds = Math.floor( (t/1000) % 60 );
var minutes = Math.floor( (t/1000/60) % 60 );
var hours = Math.floor( (t/(1000*60*60)) % 24 );
var days = Math.floor( t/(1000*60*60*24) );
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
var timeleft = getTimeRemaining($("#countdown").data("created-at"));
$("#countdown").html(timeleft);
This should give you the required countdown in JS.
--
In regards the actual removal of a Product
, you'll have to use one of the scheduling gems, although, really, they are all covers for using a cron job
- a command called at OS-level.
Cron jobs are invoked on the OS, and they can be used to call any sort of request in any application. With Rails apps, it's best to use a rake
task, as follows:
#lib/tasks/product_removal.rake
namespace :products do
desc "Remove
task :remove => :environment do
Product.destroy_all('created_at < ?', 1.day.ago)
end
end
This would be accompanied by the appropriate cron job:
0 8 * * * /bin/bash -l -c 'cd /my/project/releases/current && RAILS_ENV=production rake products:remove 2>&1'
Great question about this here: Erase records every 60 days
Upvotes: 2