user4932805
user4932805

Reputation:

object duration ruby on rails

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

Answers (1)

Richard Peck
Richard Peck

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 %>">&nbsp;</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

Related Questions