phene-backgrounded 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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