quebert 0.0.3 → 0.0.4
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/VERSION +1 -1
- data/lib/quebert/async_sender.rb +4 -95
- data/lib/quebert/async_sender/active_record.rb +59 -0
- data/lib/quebert/async_sender/class.rb +11 -0
- data/lib/quebert/async_sender/instance.rb +51 -0
- data/lib/quebert/async_sender/object.rb +22 -0
- data/quebert.gemspec +5 -1
- data/spec/async_sender_spec.rb +24 -7
- metadata +7 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
data/lib/quebert/async_sender.rb
CHANGED
@@ -1,99 +1,8 @@
|
|
1
1
|
module Quebert
|
2
2
|
module AsyncSender
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def perform(const, meth, args)
|
8
|
-
Support.constantize(const).send(meth, *args)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.included(base)
|
13
|
-
base.send(:extend, ClassMethods)
|
14
|
-
end
|
15
|
-
|
16
|
-
module ClassMethods
|
17
|
-
def async_send(meth, *args)
|
18
|
-
ObjectJob.enqueue(self.name, meth, args)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Perform jobs on instances of classes
|
24
|
-
module Instance
|
25
|
-
class InstanceJob < Job
|
26
|
-
def perform(klass, init_args, meth, args)
|
27
|
-
Support.constantize(klass).new(init_args).send(meth, *args)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.included(base)
|
32
|
-
# Its not as simple as including initialize in a class, we
|
33
|
-
# have to do some tricks to make it work so we can put the include
|
34
|
-
# before the initialize method as opposed to after. Ah, and thanks PivotalLabs for this.
|
35
|
-
base.extend ClassMethods
|
36
|
-
base.overwrite_initialize
|
37
|
-
base.instance_eval do
|
38
|
-
def method_added(name)
|
39
|
-
return if name != :initialize
|
40
|
-
overwrite_initialize
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def initialize_with_async_sender(*args)
|
46
|
-
initialize_without_async_sender(*(@_init_args = args))
|
47
|
-
end
|
48
|
-
|
49
|
-
module ClassMethods
|
50
|
-
def overwrite_initialize
|
51
|
-
class_eval do
|
52
|
-
unless method_defined?(:initialize_with_async_sender)
|
53
|
-
define_method(:initialize_with_async_sender) do
|
54
|
-
initialize_without_async_sender
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
if instance_method(:initialize) != instance_method(:initialize_with_async_sender)
|
59
|
-
alias_method :initialize_without_async_sender, :initialize
|
60
|
-
alias_method :initialize, :initialize_with_async_sender
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def async_send(meth, *args)
|
67
|
-
InstanceJob.enqueue(self.class.name, @_init_args, meth, args)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Extend a class with both the object and instance async_send
|
72
|
-
module Class
|
73
|
-
def self.included(base)
|
74
|
-
base.send(:include, AsyncSender::Object)
|
75
|
-
base.send(:include, AsyncSender::Instance)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
module ActiveRecord
|
80
|
-
class RecordJob < Job
|
81
|
-
def perform(klass, id, meth, args)
|
82
|
-
Support.constantize(klass).find(id).send(meth, *args)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.included(base)
|
87
|
-
base.send :include, InstanceMethods
|
88
|
-
base.send :include, AsyncSender::Object
|
89
|
-
end
|
90
|
-
|
91
|
-
module InstanceMethods
|
92
|
-
def async_send(meth, *args)
|
93
|
-
RecordJob.enqueue(self.class.name, id, meth, args)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
3
|
+
autoload :Object, 'quebert/async_sender/object'
|
4
|
+
autoload :Instance, 'quebert/async_sender/instance'
|
5
|
+
autoload :Class, 'quebert/async_sender/class'
|
6
|
+
autoload :ActiveRecord, 'quebert/async_sender/active_record'
|
98
7
|
end
|
99
8
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Quebert
|
2
|
+
module AsyncSender
|
3
|
+
# I'm not sure if I want to do this or build serializers per type of object...
|
4
|
+
module ActiveRecord
|
5
|
+
# Reference an AR with the pk
|
6
|
+
class PersistedRecordJob < Job
|
7
|
+
def perform(model_name, pk, meth, args)
|
8
|
+
Support.constantize(model_name).find(pk).send(meth, *args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Serialize an unpersisted AR with the attributes on the thing.
|
13
|
+
class UnpersistedRecordJob < Job
|
14
|
+
def perform(model_name, attrs, meth, args)
|
15
|
+
self.class.deserialize(Support.constantize(model_name), attrs).send(meth, *args)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Deal with converting an AR to/from a hash that we can send over the wire.
|
19
|
+
def self.serialize(record)
|
20
|
+
record.attributes.inject({}) do |hash, (attr, val)|
|
21
|
+
hash[attr] = val
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.deserialize(model, attrs)
|
27
|
+
record = model.new
|
28
|
+
record.attributes.each do |attr, val|
|
29
|
+
record.send("#{attr}=", attrs[attr])
|
30
|
+
end
|
31
|
+
record
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.included(base)
|
36
|
+
base.send(:include, InstanceMethods)
|
37
|
+
base.send(:extend, ClassMethods)
|
38
|
+
end
|
39
|
+
|
40
|
+
module InstanceMethods
|
41
|
+
# The meat of dealing with ActiveRecord instances.
|
42
|
+
def async_send(meth, *args)
|
43
|
+
if self.new_record?
|
44
|
+
UnpersistedRecordJob.enqueue(self.class.model_name, UnpersistedRecordJob.serialize(self), meth, args)
|
45
|
+
else
|
46
|
+
PersistedRecordJob.enqueue(self.class.model_name, id, meth, args)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get the model name of the Model. Can't just do class.name on this...
|
52
|
+
module ClassMethods
|
53
|
+
def async_send(meth, *args)
|
54
|
+
Object::ObjectJob.enqueue(self.model_name, meth, args)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Quebert
|
2
|
+
module AsyncSender
|
3
|
+
# Perform jobs on instances of classes
|
4
|
+
module Instance
|
5
|
+
class InstanceJob < Job
|
6
|
+
def perform(klass, init_args, meth, args)
|
7
|
+
Support.constantize(klass).new(init_args).send(meth, *args)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
# Its not as simple as including initialize in a class, we
|
13
|
+
# have to do some tricks to make it work so we can put the include
|
14
|
+
# before the initialize method as opposed to after. Ah, and thanks PivotalLabs for this.
|
15
|
+
base.extend ClassMethods
|
16
|
+
base.overwrite_initialize
|
17
|
+
base.instance_eval do
|
18
|
+
def method_added(name)
|
19
|
+
return if name != :initialize
|
20
|
+
overwrite_initialize
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize_with_async_sender(*args)
|
26
|
+
initialize_without_async_sender(*(@_init_args = args))
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
def overwrite_initialize
|
31
|
+
class_eval do
|
32
|
+
unless method_defined?(:initialize_with_async_sender)
|
33
|
+
define_method(:initialize_with_async_sender) do
|
34
|
+
initialize_without_async_sender
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if instance_method(:initialize) != instance_method(:initialize_with_async_sender)
|
39
|
+
alias_method :initialize_without_async_sender, :initialize
|
40
|
+
alias_method :initialize, :initialize_with_async_sender
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def async_send(meth, *args)
|
47
|
+
InstanceJob.enqueue(self.class.name, @_init_args, meth, args)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Quebert
|
2
|
+
module AsyncSender
|
3
|
+
# Perform jobs on Object methods (not instances)
|
4
|
+
module Object
|
5
|
+
class ObjectJob < Job
|
6
|
+
def perform(const, meth, args)
|
7
|
+
Support.constantize(const).send(meth, *args)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
base.send(:extend, ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def async_send(meth, *args)
|
17
|
+
ObjectJob.enqueue(self.name, meth, args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/quebert.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{quebert}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Brad Gessler"]
|
@@ -29,6 +29,10 @@ Gem::Specification.new do |s|
|
|
29
29
|
"bin/quebert",
|
30
30
|
"lib/quebert.rb",
|
31
31
|
"lib/quebert/async_sender.rb",
|
32
|
+
"lib/quebert/async_sender/active_record.rb",
|
33
|
+
"lib/quebert/async_sender/class.rb",
|
34
|
+
"lib/quebert/async_sender/instance.rb",
|
35
|
+
"lib/quebert/async_sender/object.rb",
|
32
36
|
"lib/quebert/backend.rb",
|
33
37
|
"lib/quebert/backend/beanstalk.rb",
|
34
38
|
"lib/quebert/backend/in_process.rb",
|
data/spec/async_sender_spec.rb
CHANGED
@@ -59,27 +59,44 @@ describe AsyncSender::ActiveRecord do
|
|
59
59
|
"#{first_name} #{last_name}"
|
60
60
|
end
|
61
61
|
|
62
|
-
def self.
|
62
|
+
def self.emailizer(address)
|
63
63
|
address
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
67
|
before(:all) do
|
68
68
|
@q = Backend::InProcess.new
|
69
|
-
Quebert::AsyncSender::ActiveRecord::
|
69
|
+
Quebert::AsyncSender::ActiveRecord::PersistedRecordJob.backend = @q
|
70
|
+
Quebert::AsyncSender::ActiveRecord::UnpersistedRecordJob.backend = @q
|
70
71
|
Quebert::AsyncSender::Object::ObjectJob.backend = @q
|
72
|
+
end
|
73
|
+
|
74
|
+
context "persisted" do
|
75
|
+
before(:each) do
|
76
|
+
@user = User.create!(:first_name => 'Brad', :last_name => 'Gessler', :email => 'brad@bradgessler.com')
|
77
|
+
end
|
71
78
|
|
72
|
-
|
79
|
+
it "should async_send instance method" do
|
80
|
+
User.first.async_send(:name)
|
81
|
+
@q.reserve.perform.should eql(User.first.name)
|
82
|
+
end
|
73
83
|
end
|
74
84
|
|
75
|
-
|
76
|
-
|
77
|
-
|
85
|
+
context "unpersisted" do
|
86
|
+
it "should async_send instance method" do
|
87
|
+
user = User.new do |u|
|
88
|
+
u.email = 'barf@jones.com'
|
89
|
+
u.first_name = "Barf"
|
90
|
+
u.send(:write_attribute, :last_name, "Jones")
|
91
|
+
end
|
92
|
+
user.async_send(:name)
|
93
|
+
@q.reserve.perform.should eql("Barf Jones")
|
94
|
+
end
|
78
95
|
end
|
79
96
|
|
80
97
|
it "should async_send class method" do
|
81
98
|
email = "brad@bradgessler.com"
|
82
|
-
User.async_send(:
|
99
|
+
User.async_send(:emailizer, email)
|
83
100
|
@q.reserve.perform.should eql(email)
|
84
101
|
end
|
85
102
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quebert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brad Gessler
|
@@ -82,6 +82,10 @@ files:
|
|
82
82
|
- bin/quebert
|
83
83
|
- lib/quebert.rb
|
84
84
|
- lib/quebert/async_sender.rb
|
85
|
+
- lib/quebert/async_sender/active_record.rb
|
86
|
+
- lib/quebert/async_sender/class.rb
|
87
|
+
- lib/quebert/async_sender/instance.rb
|
88
|
+
- lib/quebert/async_sender/object.rb
|
85
89
|
- lib/quebert/backend.rb
|
86
90
|
- lib/quebert/backend/beanstalk.rb
|
87
91
|
- lib/quebert/backend/in_process.rb
|