perform_later 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -4,3 +4,10 @@
4
4
  Perform later is a gem meant to work with the [Resque](http://github.com/defunkt/resque) queue system.
5
5
 
6
6
  The gem handles queuing tasks without the need to have additional "Worker" classes or with any changes to your original model/object code base.
7
+
8
+ ## Contribute / Bug reports
9
+ If you have an issue with this gem, please open an issue in the main repo, it will help tons if you could supply a failing spec with that, so I can better track where the bug is coming from, if not, no worries, just report I will do my best to address it as fast and efficient as I can.
10
+
11
+ If you want to contribute (awesome), open a feature branch, base it on master.
12
+
13
+ Be as descriptive as you can in the pull request description, just to be clear what problem you are solving or what feature are you adding.
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # init
2
+ require 'perform_later'
@@ -0,0 +1,24 @@
1
+ module ActiveRecordPerformLater
2
+ module InstanceMethods
3
+ def perform_later(queue, method, *args)
4
+ if ResquePerformLater.config['enabled']
5
+ args = ResquePerformLater.args_to_resque(args)
6
+
7
+ Resque::Job.create( queue,
8
+ ActiveRecordWorker,
9
+ self.class.name,
10
+ self.id,
11
+ method,
12
+ *args)
13
+ else
14
+ self.send( method, *args )
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.included(receiver)
20
+ receiver.send :include, InstanceMethods
21
+ end
22
+ end
23
+
24
+ ActiveRecord::Base.send :include, ActiveRecordPerformLater
@@ -0,0 +1,9 @@
1
+ class ActiveRecordWorker
2
+ def self.perform(klass, id, method, *args)
3
+ args = ResquePerformLater.args_from_resque(args)
4
+ runner_klass = eval(klass)
5
+
6
+ record = runner_klass.where(:id => id).first
7
+ record.send(method, *args) if record
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module ObjectPerformLater
2
+ def perform_later(queue, method, *args)
3
+ if ResquePerformLater.config['enabled']
4
+ args = ResquePerformLater.args_to_resque(args)
5
+ Resque::Job.create(queue, ObjectWorker, self.name, method, *args)
6
+ else
7
+ self.send(method, *args)
8
+ end
9
+ end
10
+ end
11
+
12
+ Object.send :include, ObjectPerformLater
@@ -0,0 +1,10 @@
1
+ class ObjectWorker
2
+ # @param klass_name [The class name that you should work on]
3
+ # @param method [method you should send on the class]
4
+ # @param args [method args]
5
+ def self.perform(klass_name, method, *args)
6
+ args = ResquePerformLater.args_from_resque(args)
7
+
8
+ klass_name.constantize.send(method, *args)
9
+ end
10
+ end
data/lib/perform_later.rb CHANGED
@@ -1,4 +1,11 @@
1
- require "perform_later/version"
1
+ require 'perform_later/version'
2
+ require 'active_record'
3
+ require 'resque_perform_later'
4
+ require 'resque_mailer_patch'
5
+ require 'object_worker'
6
+ require 'object_perform_later'
7
+ require 'active_record_worker'
8
+ require 'active_record_perform_later'
2
9
 
3
10
  module PerformLater
4
11
  # Your code goes here...
@@ -1,3 +1,3 @@
1
1
  module PerformLater
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,17 @@
1
+ module Resque
2
+ module Mailer
3
+ module ClassMethods
4
+ def perform(action, *args)
5
+ args = ResquePerformLater.args_from_resque(args)
6
+ self.send(:new, action, *args).message.deliver
7
+ end
8
+ end
9
+
10
+ class MessageDecoy
11
+ def deliver
12
+ args = ResquePerformLater.args_to_resque(@args)
13
+ resque.enqueue(@mailer_class, @method_name, *args)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,66 @@
1
+ class ResquePerformLater
2
+ APP_ROOT = File.expand_path((defined?(Rails) && Rails.root.to_s.length > 0) ? Rails.root : ".") unless defined?(APP_ROOT)
3
+ DEFAULT_CONFIG_PATH = File.join(APP_ROOT, 'config', 'resque_perform_later.yml')
4
+ DEFAULT_CONFIG = {
5
+ 'enabled' => true
6
+ }
7
+
8
+ # inspired by DelayedJob
9
+
10
+ CLASS_STRING_FORMAT = /^CLASS\:([A-Z][\w\:]+)$/
11
+ AR_STRING_FORMAT = /^AR\:([A-Z][\w\:]+)\:(\d+)$/
12
+ YAML_STRING_FORMAT = /\A---/
13
+
14
+ def self.args_to_resque(*args)
15
+ args = args.map { |o|
16
+ case o
17
+ when ActiveRecord::Base
18
+ "AR:#{o.class.name}:#{o.id}"
19
+ when Class, Module
20
+ "CLASS:#{o.name}"
21
+ when Hash
22
+ o.to_yaml
23
+ else
24
+ o
25
+ end
26
+ } if args
27
+ end
28
+
29
+ def self.args_from_resque(*args)
30
+ args = args.map { |o|
31
+ if o
32
+ case o
33
+ when CLASS_STRING_FORMAT then $1.constantize
34
+ when AR_STRING_FORMAT then $1.constantize.find_by_id($2)
35
+ when YAML_STRING_FORMAT then YAML.load(o)
36
+ else o
37
+ end
38
+ end
39
+ } if args
40
+ end
41
+
42
+ private
43
+ def self.env_str
44
+ if defined? Rails
45
+ Rails.env.to_s
46
+ elsif defined? Rack
47
+ Rack.env.to_s
48
+ else
49
+ 'production'
50
+ end
51
+ end
52
+
53
+ @@_config = nil
54
+
55
+ def self.config
56
+ return @@_config if @@_config && self.env_str != 'development'
57
+
58
+ if File.exists?(DEFAULT_CONFIG_PATH)
59
+ config = YAML.load(ERB.new(IO.read(DEFAULT_CONFIG_PATH)).result)[self.env_str]
60
+ end
61
+
62
+ config = {}.merge(DEFAULT_CONFIG || {}).merge(config || {})
63
+
64
+ @@_config = config
65
+ end
66
+ end
data/license ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) Avi Tzurel
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.
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.version = PerformLater::VERSION
8
8
  s.authors = ["Avi Tzurel"]
9
9
  s.email = ["avi@kensodev.com"]
10
- s.homepage = ""
10
+ s.homepage = "http://www.github.com/kensodev/perform_later"
11
11
  s.summary = %q{Queue any method in any class or instance with no need for additional Worker class and no extra code}
12
12
  s.description = %q{Queue any method in any class or instance with no need for additional Worker class and no extra code}
13
13
 
@@ -19,6 +19,11 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ["lib"]
20
20
 
21
21
  # specify any dependencies here; for example:
22
- # s.add_development_dependency "rspec"
23
- # s.add_runtime_dependency "rest-client"
22
+ s.add_dependency 'activerecord', ">= 3.0.0"
23
+ s.add_dependency 'redis'
24
+ s.add_dependency 'resque'
25
+
26
+ s.add_development_dependency 'rake'
27
+ s.add_development_dependency 'rspec'
28
+ s.add_development_dependency 'sqlite3'
24
29
  end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe ResquePerformLater do
4
+ let(:user) { User.create }
5
+
6
+ context "args to resque" do
7
+ it "should convert the AR object to the proper string" do
8
+ user_id = user.id
9
+
10
+ ResquePerformLater.args_to_resque(user).length.should == 1
11
+ ResquePerformLater.args_to_resque(user)[0].should == "AR:User:#{user_id}"
12
+ end
13
+
14
+ it "should convert a hash into YAML string so that Resque will be able to JSON convert it" do
15
+ hash = {name: "something", other: "something else"}
16
+ ResquePerformLater.args_to_resque(hash)[0].class.name.should == "String"
17
+ end
18
+
19
+ it "should be able to load a yaml from the string and translate it into the same hash again" do
20
+ hash = {name: "something", other: "something else"}
21
+ yaml = ResquePerformLater.args_to_resque(hash)[0]
22
+
23
+ loaded_yaml = YAML.load(yaml)
24
+
25
+ loaded_yaml[:name].should == "something"
26
+ loaded_yaml[:other].should == "something else"
27
+ end
28
+
29
+ it "should convert a class to the proper string representation" do
30
+ klass = User
31
+ ResquePerformLater.args_to_resque(klass)[0].should == "CLASS:User"
32
+ end
33
+ end
34
+
35
+ context "args from resque" do
36
+ it "should give me a hash back when I pass a yaml representation of it" do
37
+ hash = {name: "something", other: "something else"}
38
+ yaml = hash.to_yaml
39
+
40
+ args = ResquePerformLater.args_from_resque(yaml)
41
+ args[0].class.name.should == "Hash"
42
+ args[0][:name].should == "something"
43
+ args[0][:other].should == "something else"
44
+ end
45
+
46
+ it "Should give me a user model back when I pass the proper string" do
47
+ args = ResquePerformLater.args_from_resque("AR:User:#{user.id}")
48
+ args[0].should == user
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,55 @@
1
+ require "perform_later"
2
+ require "rspec"
3
+ require "support/database_connection"
4
+ require "support/database_models"
5
+ require "redis"
6
+
7
+ RSpec.configure do |config|
8
+ config.mock_with :rspec
9
+
10
+ config.before(:all) do
11
+ dir = File.join(File.dirname(__FILE__), 'support/db')
12
+
13
+ old_db = File.join(dir, 'test.sqlite3')
14
+ FileUtils.rm(old_db) if File.exists?(old_db)
15
+ FileUtils.cp(File.join(dir, '.blank.sqlite3'), File.join(dir, 'test.sqlite3'))
16
+ end
17
+
18
+ root = File.dirname(__FILE__)
19
+ REDIS_PID = File.join(root, "tmp/pids/redis-test.pid")
20
+ REDIS_CACHE_PATH = File.join(root, "tmp/cache/")
21
+
22
+ FileUtils.mkdir_p File.join(root, "tmp/pids")
23
+ FileUtils.mkdir_p File.join(root, "tmp/cache")
24
+
25
+ config.before(:suite) do
26
+ redis_options = {
27
+ "daemonize" => 'yes',
28
+ "pidfile" => REDIS_PID,
29
+ "port" => 9726,
30
+ "timeout" => 300,
31
+ "save 900" => 1,
32
+ "save 300" => 1,
33
+ "save 60" => 10000,
34
+ "dbfilename" => "dump.rdb",
35
+ "dir" => REDIS_CACHE_PATH,
36
+ "loglevel" => "debug",
37
+ "logfile" => "stdout",
38
+ "databases" => 16
39
+ }.map { |k, v| "#{k} #{v}" }.join('\n')
40
+ cmd = "echo '#{redis_options}' | redis-server -"
41
+ system cmd
42
+
43
+
44
+ uri = URI.parse("http://localhost:9726")
45
+ $redis = Redis.new(host: uri.host, port: uri.port)
46
+ end
47
+
48
+ config.after(:suite) do
49
+ %x{
50
+ cat #{REDIS_PID} | xargs kill -QUIT
51
+ rm -f #{REDIS_CACHE_PATH}dump.rdb
52
+ rm -f #{REDIS_PID}
53
+ }
54
+ end
55
+ end
@@ -0,0 +1 @@
1
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: File.join(File.dirname(__FILE__), "db/test.sqlite3")
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+
3
+ end
Binary file
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perform_later
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,73 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
  date: 2012-02-19 00:00:00.000000000 Z
13
- dependencies: []
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: &70120073048240 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70120073048240
25
+ - !ruby/object:Gem::Dependency
26
+ name: redis
27
+ requirement: &70120073047640 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70120073047640
36
+ - !ruby/object:Gem::Dependency
37
+ name: resque
38
+ requirement: &70120073046940 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70120073046940
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: &70120073046500 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70120073046500
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &70120073045940 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70120073045940
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: &70120073045260 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70120073045260
14
80
  description: Queue any method in any class or instance with no need for additional
15
81
  Worker class and no extra code
16
82
  email:
@@ -23,10 +89,24 @@ files:
23
89
  - Gemfile
24
90
  - README.md
25
91
  - Rakefile
92
+ - init.rb
93
+ - lib/active_record_perform_later.rb
94
+ - lib/active_record_worker.rb
95
+ - lib/object_perform_later.rb
96
+ - lib/object_worker.rb
26
97
  - lib/perform_later.rb
27
98
  - lib/perform_later/version.rb
99
+ - lib/resque_mailer_patch.rb
100
+ - lib/resque_perform_later.rb
101
+ - license
28
102
  - perform_later.gemspec
29
- homepage: ''
103
+ - spec/lib/resque_perform_later_spec.rb
104
+ - spec/spec_helper.rb
105
+ - spec/support/database_connection.rb
106
+ - spec/support/database_models.rb
107
+ - spec/support/db/.blank.sqlite3
108
+ - spec/support/db/test.sqlite3
109
+ homepage: http://www.github.com/kensodev/perform_later
30
110
  licenses: []
31
111
  post_install_message:
32
112
  rdoc_options: []
@@ -51,4 +131,10 @@ signing_key:
51
131
  specification_version: 3
52
132
  summary: Queue any method in any class or instance with no need for additional Worker
53
133
  class and no extra code
54
- test_files: []
134
+ test_files:
135
+ - spec/lib/resque_perform_later_spec.rb
136
+ - spec/spec_helper.rb
137
+ - spec/support/database_connection.rb
138
+ - spec/support/database_models.rb
139
+ - spec/support/db/.blank.sqlite3
140
+ - spec/support/db/test.sqlite3