Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-blocking Timed event in Ruby like JavaScript setTimeout

I need to change a property on a class a few minutes after it it initialized. I attempted to use sleep inside a function but it delayed execution of everything:

active = true

def deactivate
  sleep 120
  puts 'deactivate'
  active = false
end

deactivate
puts active

What I was hoping would happen is true would log out first then two minutes later deactivate would log. However, what happens is deactivate then false log out after two minutes.

In JavaScript I would do something like:

var active = true;
setTimeout(function(){
  console.log('deactivate');
  active = false;
},120000);
console.log(active);
like image 238
Kyle Werner Avatar asked Oct 03 '15 04:10

Kyle Werner


3 Answers

Using @ihaztehcodez's suggestion of a Thread I came up with the simple solution I was looking for:

Thread.new do
  sleep 120
  puts 'deactivate'
  active = false
end

His warning about persistence doesn't worry me in this case since I am using it for non-critical notifications. If the execution was critical then storing something in a database like @spickermann said or using a library like @k-m-rakibul-islam suggested would be the better solution.

like image 133
Kyle Werner Avatar answered Oct 10 '22 22:10

Kyle Werner


Looks overkill for this task, but you can use delayed_job to run a task at a future time asynchronously.

  def deactivate
     puts 'deactivate'
     active = false
  end

  active = true
  handle_asynchronously :deactivate, :run_at => Proc.new { 2.minutes.from_now }
like image 21
K M Rakibul Islam Avatar answered Oct 10 '22 22:10

K M Rakibul Islam


Well, it seems to me (When I try this code) the active and deactivate is out of order. So why not do this?:

   active = true

   def deactivate
     sleep 120
     puts 'deactivate'
     active = false
   end

   puts active
   deactivate

It works perfectly.

like image 1
Yahs Hef Avatar answered Oct 10 '22 22:10

Yahs Hef