phene-backgrounded 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ .document
2
+ *.sw?
3
+ .DS_Store
4
+ coverage
5
+ rdoc
6
+ pkg
7
+ *.sqlite3
8
+ *.log
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Ryan Sonnek
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,78 @@
1
+ = Backgrounded
2
+
3
+ The cleanest way to integrate background processing into your application.
4
+
5
+ Backgrounded provides a thin wrapper around any background processing framework that implements the Backgrounded handler API which makes it trivial to swap out processing frameworks with no impact to your code.
6
+
7
+ = Features
8
+ * clean and concise API which removes any dependency on external "worker" jobs and allows you to execute any model method in the background
9
+ * integrates with any background processing framework (DelayedJob, Resque, JobFu, Workling, etc)
10
+ * background methods can be actually unit tested by using an 'in process' runner
11
+
12
+ = Usage
13
+
14
+ #declaration
15
+ class User
16
+ backgrounded :do_stuff
17
+ def do_stuff
18
+ # do all your work here
19
+ end
20
+ end
21
+
22
+ #usage
23
+ user = User.new
24
+ user.do_stuff_backgrounded
25
+
26
+ = Installation
27
+
28
+ Command line installation
29
+
30
+ sudo gem install backgrounded
31
+
32
+ Rails environment.rb configuration
33
+
34
+ config.gem 'backgrounded'
35
+
36
+ Bundler Gemfile configuration
37
+
38
+ gem 'backgrounded'
39
+
40
+ = Configuration
41
+
42
+ Backgrounded includes several configurable implementations out of the box for most popular background frameworks.
43
+ If your framework isn't included, it's trivial to write your own implementation.
44
+ Submit a patch and we may consider it for official distribution!
45
+
46
+ == DelayedJob
47
+ see http://github.com/tobi/delayed_job/tree/master
48
+
49
+ # config/initializers/backgrounded.rb
50
+ require 'backgrounded/handler/delayed_job_handler'
51
+ Backgrounded.handler = Backgrounded::Handler::DelayedJobHandler.new
52
+
53
+ == Resque
54
+ see http://github.com/defunkt/resque/
55
+
56
+ # config/initializers/backgrounded.rb
57
+ require 'backgrounded/handler/resque_handler'
58
+ Backgrounded.handler = Backgrounded::Handler::ResqueHandler.new
59
+
60
+ == JobFu
61
+ see http://github.com/jnstq/job_fu/tree
62
+
63
+ # config/initializers/backgrounded.rb
64
+ Backgrounded.handler = JobFu::Backgrounded::Handler.new
65
+
66
+ == Custom Handlers
67
+
68
+ # config/initializers/backgrounded.rb
69
+ class MyHandler
70
+ def request(object, method, *args)
71
+ #process the call however you want!
72
+ end
73
+ end
74
+ Backgrounded.handler = MyHandler.new
75
+
76
+ == Copyright
77
+
78
+ Copyright (c) 2009 Ryan Sonnek. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "backgrounded"
8
+ gem.summary = %Q{Simple API to run Model methods in the background}
9
+ gem.email = "ryan.sonnek@gmail.com"
10
+ gem.homepage = "http://github.com/wireframe/backgrounded"
11
+ gem.authors = ["Ryan Sonnek"]
12
+ gem.add_runtime_dependency "activerecord", ">= 2.2.3"
13
+ gem.add_runtime_dependency "activesupport", ">= 2.2.3"
14
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
15
+ gem.add_development_dependency 'resque_unit', ">= 0"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
21
+ end
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test) do |test|
25
+ test.libs << 'lib' << 'test'
26
+ test.pattern = 'test/**/*_test.rb'
27
+ test.verbose = true
28
+ end
29
+
30
+ begin
31
+ require 'rcov/rcovtask'
32
+ Rcov::RcovTask.new do |test|
33
+ test.libs << 'test'
34
+ test.pattern = 'test/**/*_test.rb'
35
+ test.verbose = true
36
+ end
37
+ rescue LoadError
38
+ task :rcov do
39
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
+ end
41
+ end
42
+
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ if File.exist?('VERSION.yml')
49
+ config = YAML.load(File.read('VERSION.yml'))
50
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
51
+ else
52
+ version = ""
53
+ end
54
+
55
+ rdoc.rdoc_dir = 'rdoc'
56
+ rdoc.title = "backgrounded #{version}"
57
+ rdoc.rdoc_files.include('README*')
58
+ rdoc.rdoc_files.include('lib/**/*.rb')
59
+ end
60
+
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 6
4
+ :build:
5
+ :patch: 3
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{phene-backgrounded}
8
+ s.version = "0.6.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ryan Sonnek"]
12
+ s.date = %q{2010-10-27}
13
+ s.email = %q{ryan.sonnek@gmail.com}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE",
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "LICENSE",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION.yml",
24
+ "backgrounded.gemspec",
25
+ "lib/backgrounded.rb",
26
+ "lib/backgrounded/class_methods.rb",
27
+ "lib/backgrounded/handler/delayed_job_handler.rb",
28
+ "lib/backgrounded/handler/inprocess_handler.rb",
29
+ "lib/backgrounded/handler/resque_handler.rb",
30
+ "lib/backgrounded/handler/workling_handler.rb",
31
+ "test/backgrounded/handler/delayed_job_handler_test.rb",
32
+ "test/backgrounded/handler/resque_handler_test.rb",
33
+ "test/backgrounded/handler/workling_handler_test.rb",
34
+ "test/backgrounded_test.rb",
35
+ "test/database.yml",
36
+ "test/test_helper.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/wireframe/backgrounded}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.7}
42
+ s.summary = %q{Simple API to run Model methods in the background}
43
+ s.test_files = [
44
+ "test/backgrounded/handler/delayed_job_handler_test.rb",
45
+ "test/backgrounded/handler/resque_handler_test.rb",
46
+ "test/backgrounded/handler/workling_handler_test.rb",
47
+ "test/backgrounded_test.rb",
48
+ "test/test_helper.rb"
49
+ ]
50
+
51
+ if s.respond_to? :specification_version then
52
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
53
+ s.specification_version = 3
54
+
55
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
56
+ s.add_runtime_dependency(%q<activerecord>, [">= 2.2.3"])
57
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.2.3"])
58
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
59
+ s.add_development_dependency(%q<resque_unit>, [">= 0"])
60
+ else
61
+ s.add_dependency(%q<activerecord>, [">= 2.2.3"])
62
+ s.add_dependency(%q<activesupport>, [">= 2.2.3"])
63
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
64
+ s.add_dependency(%q<resque_unit>, [">= 0"])
65
+ end
66
+ else
67
+ s.add_dependency(%q<activerecord>, [">= 2.2.3"])
68
+ s.add_dependency(%q<activesupport>, [">= 2.2.3"])
69
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
70
+ s.add_dependency(%q<resque_unit>, [">= 0"])
71
+ end
72
+ end
73
+
@@ -0,0 +1,14 @@
1
+ require 'active_support/all'
2
+
3
+ require File.join(File.dirname(__FILE__), 'backgrounded', 'class_methods')
4
+ require File.join(File.dirname(__FILE__), 'backgrounded', 'handler', 'inprocess_handler')
5
+
6
+ Object.send(:include, Backgrounded::ClassMethods)
7
+
8
+ module Backgrounded
9
+ mattr_accessor :handler
10
+ def self.handler
11
+ @@handler ||= Backgrounded::Handler::InprocessHandler.new
12
+ end
13
+ end
14
+
@@ -0,0 +1,26 @@
1
+ module Backgrounded
2
+ module ClassMethods
3
+ def backgrounded(*args)
4
+ options = args.extract_options!
5
+ methods_with_options = args.inject({}) do |hash, method| hash[method] = {}; hash end
6
+ methods_with_options.merge! options
7
+ methods_with_options.each_pair do |method, options|
8
+ method_basename, punctuation = method.to_s.sub(/([?!=])$/, ''), $1
9
+ if options[:class_method]
10
+ class_eval <<-EOS
11
+ def self.#{method_basename}_backgrounded#{punctuation}(*args)
12
+ Backgrounded.handler.request(self, :#{method}, *args)
13
+ end
14
+ EOS
15
+ else
16
+ define_method "#{method_basename}_backgrounded#{punctuation}" do |*args|
17
+ Backgrounded.handler.request(self, method, *args)
18
+ end
19
+ end
20
+ end
21
+ cattr_accessor :backgrounded_options
22
+ self.backgrounded_options ||= {}
23
+ self.backgrounded_options.merge! methods_with_options
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ require 'delayed_job'
2
+
3
+ module Backgrounded
4
+ module Handler
5
+ # invoke the operation in the background using delayed job
6
+ # see http://github.com/tobi/delayed_job/tree/master
7
+ class DelayedJobHandler
8
+ def request(object, method, *args)
9
+ object.send_later(method.to_sym, *args)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Backgrounded
2
+ module Handler
3
+ #simple handler to process synchronously and not actually in the background
4
+ #useful for testing
5
+ class InprocessHandler
6
+ def request(object, method, *args)
7
+ object.send method, *args
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ require 'resque'
2
+
3
+ module Backgrounded
4
+ module Handler
5
+ #enque requests in resque
6
+ class ResqueHandler
7
+ DEFAULT_QUEUE = 'backgrounded'
8
+ @@queue = DEFAULT_QUEUE
9
+
10
+ def request(object, method, *args)
11
+ @@queue = object.backgrounded_options[method.to_sym][:queue] || DEFAULT_QUEUE
12
+ if object.is_a? Class
13
+ Resque.enqueue(ResqueHandler, object.name, 0, method, *args)
14
+ else
15
+ Resque.enqueue(ResqueHandler, object.class.name, object.id, method, *args)
16
+ end
17
+ end
18
+ def self.queue
19
+ @@queue
20
+ end
21
+ def self.perform(clazz, id, method, *args)
22
+ clazz = clazz.constantize
23
+ if clazz.backgrounded_options[method.to_sym][:class_method]
24
+ clazz.send(method, *args)
25
+ else
26
+ clazz.find(id).send(method, *args)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ class Backgrounded::Handler::WorklingHandler
2
+ def request(object, method, *args)
3
+ if object.is_a? Class
4
+ options = {
5
+ :class => object.name,
6
+ :class_method => true,
7
+ :method => method,
8
+ :params => args
9
+ }
10
+ else
11
+ options = {
12
+ :class => object.class.name,
13
+ :class_method => false,
14
+ :id => object.id,
15
+ :method => method,
16
+ :params => args
17
+ }
18
+ end
19
+ BackgroundedWorker.async_perform options
20
+ end
21
+
22
+ class BackgroundedWorker < Workling::Base
23
+ def perform(options = {})
24
+ clazz = options[:class].constantize
25
+ if options[:class_method]
26
+ clazz.send(options[:method], *options[:params])
27
+ else
28
+ clazz.find(options[:id]).send(options[:method], *options[:params])
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,56 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+ require 'backgrounded/handler/delayed_job_handler'
3
+ require 'delayed/backend/active_record'
4
+
5
+ ActiveRecord::Schema.define(:version => 1) do
6
+ create_table :users, :force => true do |t|
7
+ t.column :name, :string
8
+ end
9
+ create_table :delayed_jobs, :force => true do |table|
10
+ table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
11
+ table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
12
+ table.text :handler # YAML-encoded string of the object that will do work
13
+ table.string :last_error # reason for last failure (See Note below)
14
+ table.datetime :run_at # When to run. Could be Time.now for immediately, or sometime in the future.
15
+ table.datetime :locked_at # Set when a client is working on this object
16
+ table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
17
+ table.string :locked_by # Who is working on this object (if locked)
18
+ table.timestamps
19
+ end
20
+ end
21
+
22
+ class DelayedJobHandlerTest < Test::Unit::TestCase
23
+
24
+ class User < ActiveRecord::Base
25
+ backgrounded :do_stuff
26
+
27
+ def do_stuff
28
+ end
29
+ end
30
+
31
+ context 'when backgrounded is configured with delayed_job' do
32
+ setup do
33
+ Delayed::Worker.backend = :active_record
34
+ @handler = Backgrounded::Handler::DelayedJobHandler.new
35
+ Backgrounded.handler = @handler
36
+ end
37
+
38
+ should 'be configured' do
39
+ fail 'delayed job not recognizing activerecord config'
40
+ end
41
+ # context 'a persisted object with a single backgrounded method' do
42
+ # setup do
43
+ # @user = User.create
44
+ # end
45
+ # context "invoking backgrounded method" do
46
+ # setup do
47
+ # @user.do_stuff_backgrounded
48
+ # end
49
+ # should_create Delayed::Job
50
+ # should 'create delayed job' do
51
+ # job = Delayed::Job.last
52
+ # end
53
+ # end
54
+ # end
55
+ end
56
+ end
@@ -0,0 +1,93 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+ require 'backgrounded/handler/resque_handler'
3
+
4
+ ActiveRecord::Schema.define(:version => 1) do
5
+ create_table :users, :force => true do |t|
6
+ t.column :name, :string
7
+ end
8
+
9
+ create_table :posts, :force => true do |t|
10
+ t.column :title, :string
11
+ end
12
+
13
+ create_table :klassies, :force => true do |t|
14
+ t.column :foo, :string
15
+ end
16
+ end
17
+
18
+ class ResqueHandlerTest < Test::Unit::TestCase
19
+ class User < ActiveRecord::Base
20
+ backgrounded :do_stuff
21
+
22
+ def do_stuff
23
+ end
24
+ end
25
+
26
+ class Post < ActiveRecord::Base
27
+ backgrounded :do_stuff => {:queue => 'important'}
28
+
29
+ def do_stuff
30
+ end
31
+ end
32
+
33
+ class Klassy < ActiveRecord::Base
34
+ backgrounded :do_stuff => {:class_method => true}
35
+
36
+ def self.do_stuff
37
+ end
38
+ end
39
+
40
+ context 'when backgrounded is configured with resque' do
41
+ setup do
42
+ Resque.reset!
43
+ @handler = Backgrounded::Handler::ResqueHandler.new
44
+ Backgrounded.handler = @handler
45
+ end
46
+
47
+ context 'a persisted object with a single backgrounded method' do
48
+ setup do
49
+ @user = User.create
50
+ end
51
+ context "invoking backgrounded method" do
52
+ setup do
53
+ @user.do_stuff_backgrounded
54
+ end
55
+ should "enqueue job to resque" do
56
+ assert_queued Backgrounded::Handler::ResqueHandler
57
+ assert_equal Backgrounded::Handler::ResqueHandler::DEFAULT_QUEUE, Resque.queue_from_class(Backgrounded::Handler::ResqueHandler)
58
+ end
59
+ context "running background job" do
60
+ should "invoke method on user object" do
61
+ User.any_instance.expects(:do_stuff)
62
+ Resque.run!
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'a persisted object with backgrounded method with options' do
68
+ setup do
69
+ @post = Post.create
70
+ end
71
+ context "invoking backgrounded method" do
72
+ setup do
73
+ @post.do_stuff_backgrounded
74
+ end
75
+ should "use configured queue" do
76
+ assert_equal 'important', Backgrounded::Handler::ResqueHandler.queue
77
+ assert_equal 'important', Resque.queue_from_class(Backgrounded::Handler::ResqueHandler)
78
+ end
79
+ end
80
+ end
81
+
82
+ context 'a class with backgrounded method with objects' do
83
+ setup do
84
+ Klassy.do_stuff_backgrounded
85
+ end
86
+ should "envoke method on class" do
87
+ Klassy.expects :do_stuff
88
+ Resque.run!
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,65 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+ RAILS_DEFAULT_LOGGER = Logger.new 'foo'
3
+ RAILS_ENV = 'test'
4
+ require 'newrelic_rpm'
5
+ require 'memcache'
6
+ require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'socialcast', 'vendor', 'plugins', 'workling', 'lib', 'workling')
7
+ require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'socialcast', 'vendor', 'plugins', 'workling', 'lib', 'workling', 'base')
8
+ require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'socialcast', 'vendor', 'plugins', 'workling', 'lib', 'workling', 'discovery')
9
+ require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'socialcast', 'vendor', 'plugins', 'workling', 'lib', 'workling', 'routing', 'class_and_method_routing')
10
+ require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'socialcast', 'vendor', 'plugins', 'workling', 'lib', 'workling', 'remote', 'invokers', 'threaded_poller')
11
+ require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'socialcast', 'vendor', 'plugins', 'workling', 'lib', 'workling', 'remote')
12
+ require 'backgrounded/handler/workling_handler'
13
+
14
+ ActiveRecord::Schema.define(:version => 1) do
15
+ create_table :users, :force => true do |t|
16
+ t.column :name, :string
17
+ end
18
+ create_table :klassies, :force => true do |t|
19
+ t.column :foo, :string
20
+ end
21
+ end
22
+
23
+ class WorklingHandlerTest < Test::Unit::TestCase
24
+
25
+ class User < ActiveRecord::Base
26
+ backgrounded :do_stuff
27
+
28
+ def do_stuff
29
+ end
30
+ end
31
+
32
+ class Klassy < ActiveRecord::Base
33
+ backgrounded :do_stuff => {:class_method => true}
34
+
35
+ def self.do_stuff
36
+ end
37
+ end
38
+
39
+ context 'when backgrounded is configured with workling' do
40
+ setup do
41
+ @handler = Backgrounded::Handler::WorklingHandler.new
42
+ Backgrounded.handler = @handler
43
+ end
44
+
45
+ context 'a persisted object with a single backgrounded method' do
46
+ setup do
47
+ @user = User.create
48
+ end
49
+ context "invoking backgrounded method" do
50
+ setup do
51
+ User.any_instance.expects(:do_stuff).with('a string')
52
+ @user.do_stuff_backgrounded 'a string'
53
+ end
54
+ should 'dispatch through workling back to the object' do end #see expectations
55
+ end
56
+
57
+ context 'a class with a single backgrounded method' do
58
+ should 'invoke background method' do
59
+ Klassy.expects(:do_stuff).with('a string')
60
+ Klassy.do_stuff_backgrounded 'a string'
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,126 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class BackgroundedTest < Test::Unit::TestCase
4
+
5
+ class User
6
+ backgrounded :do_stuff
7
+
8
+ def do_stuff
9
+ end
10
+ end
11
+
12
+ class Person
13
+ backgrounded :do_stuff
14
+
15
+ def do_stuff(name, place, location)
16
+ end
17
+ end
18
+
19
+ class Post
20
+ backgrounded :do_stuff, :notify_users
21
+
22
+ def do_stuff
23
+ end
24
+ def notify_users
25
+ end
26
+ end
27
+
28
+ class Comment
29
+ backgrounded :delete_spam!
30
+
31
+ def delete_spam!
32
+ end
33
+ end
34
+
35
+ class Dog
36
+ backgrounded :bark => {:priority => :low}
37
+
38
+ def bark
39
+ end
40
+ end
41
+
42
+ class Entry
43
+ backgrounded :do_stuff
44
+ backgrounded :notify_users
45
+
46
+ def do_stuff
47
+ end
48
+ def notify_users
49
+ end
50
+ end
51
+
52
+ class Klassy
53
+ backgrounded :be_klassy => {:class_method => true}
54
+
55
+ def self.be_klassy
56
+ end
57
+ end
58
+
59
+ context 'an object with a single backgrounded method' do
60
+ setup do
61
+ @user = User.new
62
+ end
63
+ should "execute method in background" do
64
+ @user.expects(:do_stuff)
65
+ @user.do_stuff_backgrounded
66
+ end
67
+ end
68
+
69
+ context 'an object with a backgrounded method that accepts parameters' do
70
+ setup do
71
+ @person = Person.new
72
+ end
73
+ should 'forward them' do
74
+ @person.expects(:do_stuff).with('ryan', 2, 3)
75
+ @person.do_stuff_backgrounded('ryan', 2, 3)
76
+ end
77
+ end
78
+
79
+ context 'an object with a backgrounded method included punctuation' do
80
+ setup do
81
+ @comment = Comment.new
82
+ end
83
+ should 'move punctuation to the end of the new method' do
84
+ assert @comment.respond_to?(:'delete_spam_backgrounded!')
85
+ end
86
+ end
87
+
88
+ context 'an object with multiple backgrounded methods' do
89
+ setup do
90
+ @post = Post.new
91
+ end
92
+ should "execute method either method in background" do
93
+ @post.expects(:do_stuff)
94
+ @post.do_stuff_backgrounded
95
+
96
+ @post.expects(:notify_users)
97
+ @post.notify_users_backgrounded
98
+ end
99
+ end
100
+
101
+ context 'an object with multiple backgrounded invokations' do
102
+ setup do
103
+ @post = Entry.new
104
+ end
105
+ should "setup options for both methods" do
106
+ assert_not_nil Entry.backgrounded_options[:do_stuff]
107
+ assert_not_nil Entry.backgrounded_options[:notify_users]
108
+ end
109
+ end
110
+
111
+ context 'an object with backgrounded method options' do
112
+ setup do
113
+ @dog = Dog.new
114
+ end
115
+ should 'save method options for future use' do
116
+ assert_equal :low, @dog.backgrounded_options[:bark][:priority]
117
+ end
118
+ end
119
+
120
+ context 'a class with backgrounded method' do
121
+ should "execute class method in background" do
122
+ Klassy.expects(:be_klassy)
123
+ Klassy.be_klassy_backgrounded
124
+ end
125
+ end
126
+ end
data/test/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ sqlite:
2
+ adapter: sqlite3
3
+ database: test/backgrounded.sqlite3
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ require 'active_record'
6
+ require 'resque_unit'
7
+
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+ require 'backgrounded'
11
+
12
+ config = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'database.yml')))
13
+ ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
14
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite'])
15
+
16
+ class Test::Unit::TestCase
17
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: phene-backgrounded
3
+ version: !ruby/object:Gem::Version
4
+ hash: 3
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 2
10
+ version: 0.6.2
11
+ platform: ruby
12
+ authors:
13
+ - Ryan Sonnek
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-27 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activerecord
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 1
30
+ segments:
31
+ - 2
32
+ - 2
33
+ - 3
34
+ version: 2.2.3
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: activesupport
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 1
46
+ segments:
47
+ - 2
48
+ - 2
49
+ - 3
50
+ version: 2.2.3
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: thoughtbot-shoulda
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :development
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: resque_unit
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ type: :development
80
+ version_requirements: *id004
81
+ description:
82
+ email: ryan.sonnek@gmail.com
83
+ executables: []
84
+
85
+ extensions: []
86
+
87
+ extra_rdoc_files:
88
+ - LICENSE
89
+ - README.rdoc
90
+ files:
91
+ - .gitignore
92
+ - LICENSE
93
+ - README.rdoc
94
+ - Rakefile
95
+ - VERSION.yml
96
+ - backgrounded.gemspec
97
+ - lib/backgrounded.rb
98
+ - lib/backgrounded/class_methods.rb
99
+ - lib/backgrounded/handler/delayed_job_handler.rb
100
+ - lib/backgrounded/handler/inprocess_handler.rb
101
+ - lib/backgrounded/handler/resque_handler.rb
102
+ - lib/backgrounded/handler/workling_handler.rb
103
+ - test/backgrounded/handler/delayed_job_handler_test.rb
104
+ - test/backgrounded/handler/resque_handler_test.rb
105
+ - test/backgrounded/handler/workling_handler_test.rb
106
+ - test/backgrounded_test.rb
107
+ - test/database.yml
108
+ - test/test_helper.rb
109
+ has_rdoc: true
110
+ homepage: http://github.com/wireframe/backgrounded
111
+ licenses: []
112
+
113
+ post_install_message:
114
+ rdoc_options:
115
+ - --charset=UTF-8
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ hash: 3
124
+ segments:
125
+ - 0
126
+ version: "0"
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ requirements: []
137
+
138
+ rubyforge_project:
139
+ rubygems_version: 1.3.7
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: Simple API to run Model methods in the background
143
+ test_files:
144
+ - test/backgrounded/handler/delayed_job_handler_test.rb
145
+ - test/backgrounded/handler/resque_handler_test.rb
146
+ - test/backgrounded/handler/workling_handler_test.rb
147
+ - test/backgrounded_test.rb
148
+ - test/test_helper.rb