Skip to content

Commit

Permalink
Make performable method work with Mongo
Browse files Browse the repository at this point in the history
  • Loading branch information
bkeepers committed Jan 19, 2010
1 parent 661f0f3 commit da4b5d0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
36 changes: 19 additions & 17 deletions lib/delayed/performable_method.rb
Expand Up @@ -2,6 +2,10 @@ module Delayed
class PerformableMethod < Struct.new(:object, :method, :args)
CLASS_STRING_FORMAT = /^CLASS\:([A-Z][\w\:]+)$/
AR_STRING_FORMAT = /^AR\:([A-Z][\w\:]+)\:(\d+)$/
MM_STRING_FORMAT = /^MM\:([A-Z][\w\:]+)\:(\w+)$/

class LoadError < StandardError
end

def initialize(object, method, args)
raise NoMethodError, "undefined method `#{method}' for #{self.inspect}" unless object.respond_to?(method)
Expand All @@ -15,41 +19,39 @@ def display_name
case self.object
when CLASS_STRING_FORMAT then "#{$1}.#{method}"
when AR_STRING_FORMAT then "#{$1}##{method}"
when MM_STRING_FORMAT then "#{$1}##{method}"
else "Unknown##{method}"
end
end

def perform
load(object).send(method, *args.map{|a| load(a)})
rescue ActiveRecord::RecordNotFound
rescue PerformableMethod::LoadError
# We cannot do anything about objects which were deleted in the meantime
true
end

private

def load(arg)
case arg
def load(obj)
case obj
when CLASS_STRING_FORMAT then $1.constantize
when AR_STRING_FORMAT then $1.constantize.find($2)
else arg
when MM_STRING_FORMAT then $1.constantize.find!($2)
else obj
end
rescue => e
Delayed::Worker.logger.warn "Could not load object for job: #{e.message}"
raise PerformableMethod::LoadError
end

def dump(arg)
case arg
when Class then class_to_string(arg)
when ActiveRecord::Base then ar_to_string(arg)
else arg
def dump(obj)
case obj
when Class then "CLASS:#{obj.name}"
when ActiveRecord::Base then "AR:#{obj.class}:#{obj.id}"
when MongoMapper::Document then "MM:#{obj.class}:#{obj.id}"
else obj
end
end

def ar_to_string(obj)
"AR:#{obj.class}:#{obj.id}"
end

def class_to_string(obj)
"CLASS:#{obj.name}"
end
end
end
44 changes: 44 additions & 0 deletions spec/mongo_job_spec.rb
Expand Up @@ -15,4 +15,48 @@
end

it_should_behave_like 'a backend'

describe "delayed method" do
class MongoStoryReader
def read(story)
"Epilog: #{story.tell}"
end
end

class MongoStory
include MongoMapper::Document
key :text, String

def tell
text
end
end

it "should ignore not found errors because they are permanent" do
story = MongoStory.create :text => 'Once upon a time…'
job = story.send_later(:tell)
story.destroy
lambda { job.invoke_job }.should_not raise_error
end

it "should store the object as string" do
story = MongoStory.create :text => 'Once upon a time…'
job = story.send_later(:tell)

job.payload_object.class.should == Delayed::PerformableMethod
job.payload_object.object.should == "MM:MongoStory:#{story.id}"
job.payload_object.method.should == :tell
job.payload_object.args.should == []
job.payload_object.perform.should == 'Once upon a time…'
end

it "should store arguments as string" do
story = MongoStory.create :text => 'Once upon a time…'
job = MongoStoryReader.new.send_later(:read, story)
job.payload_object.class.should == Delayed::PerformableMethod
job.payload_object.method.should == :read
job.payload_object.args.should == ["MM:MongoStory:#{story.id}"]
job.payload_object.perform.should == 'Epilog: Once upon a time…'
end
end
end

0 comments on commit da4b5d0

Please sign in to comment.