diff --git a/README.textile b/README.textile index 87c260721..e41ca5e29 100644 --- a/README.textile +++ b/README.textile @@ -84,6 +84,39 @@ device = Device.new device.deliver +handle_asynchronously can take as options anything you can pass to delay. In addition the values can be Proc objects allowing call time evaluation of the value. For some examples: + +
+class LongTasks
+  def send_mailer
+    # Some other code
+  end
+  handle_asynchronously :send_mailer, :priority => 20
+
+  def in_the_future
+    # Some other code
+  end
+  # 5.minutes.from_now will be evaluated when in_the_future is called
+  handle_asynchronously :in_the_future, :run_at => Proc.new { 5.minutes.from_now }
+
+  def self.when_to_run
+    2.hours.from_now
+  end
+
+  def call_a_class_method
+    # Some other code
+  end
+  handle_asynchronously :call_a_class_method, :run_at => Proc.new { when_to_run }
+
+  attr_reader :how_important
+
+  def call_an_instance_method
+    # Some other code
+  end
+  handle_asynchronously :call_an_instance_method, :priority => Proc.new {|i| i.how_important }
+end
+
+ h2. Running Jobs @script/delayed_job@ can be used to manage a background process which will start working off jobs. Make sure you've run `script/generate delayed_job`. diff --git a/lib/delayed/message_sending.rb b/lib/delayed/message_sending.rb index 8f7af9ce7..b93bcfce8 100644 --- a/lib/delayed/message_sending.rb +++ b/lib/delayed/message_sending.rb @@ -31,11 +31,21 @@ def send_at(time, method, *args) end module ClassMethods - def handle_asynchronously(method) + def handle_asynchronously(method, opts = {}) aliased_method, punctuation = method.to_s.sub(/([?!=])$/, ''), $1 with_method, without_method = "#{aliased_method}_with_delay#{punctuation}", "#{aliased_method}_without_delay#{punctuation}" define_method(with_method) do |*args| - delay.__send__(without_method, *args) + curr_opts = opts.clone + curr_opts.each_key do |key| + if (val = curr_opts[key]).is_a?(Proc) + curr_opts[key] = if val.arity == 1 + val.call(self) + else + val.call + end + end + end + delay(curr_opts).__send__(without_method, *args) end alias_method_chain method, :delay end diff --git a/spec/message_sending_spec.rb b/spec/message_sending_spec.rb index b7bfc445b..7b7f11040 100644 --- a/spec/message_sending_spec.rb +++ b/spec/message_sending_spec.rb @@ -22,6 +22,44 @@ def tell!(arg) job.payload_object.args.should == [1] }.should change { Delayed::Job.count } end + + describe 'with options' do + class Fable + class << self + attr_accessor :importance + end + def tell + end + handle_asynchronously :tell, :priority => Proc.new { self.importance } + end + + it 'should set the priority based on the Fable importance' do + Fable.importance = 10 + job = Fable.new.tell + job.priority.should == 10 + + Fable.importance = 20 + job = Fable.new.tell + job.priority.should == 20 + end + + describe 'using a proc with parament' do + class Yarn + attr_accessor :importance + def spin + end + handle_asynchronously :spin, :priority => Proc.new {|y| y.importance } + end + + it 'should set the priority based on the Fable importance' do + job = Yarn.new.tap {|y| y.importance = 10 }.spin + job.priority.should == 10 + + job = Yarn.new.tap {|y| y.importance = 20 }.spin + job.priority.should == 20 + end + end + end end context "delay" do