reactor 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/reactor/event.rb +49 -0
- data/lib/reactor/message.rb +46 -0
- data/lib/reactor/models/concerns/eventable.rb +43 -0
- data/lib/reactor/models/concerns/optionally_subclassable.rb +13 -0
- data/lib/reactor/models/subscriber.rb +42 -0
- data/lib/reactor/testing/matchers.rb +13 -0
- data/lib/reactor/version.rb +3 -0
- data/lib/reactor.rb +12 -0
- data/reactor.gemspec +24 -0
- data/spec/event_spec.rb +21 -0
- data/spec/message_spec.rb +61 -0
- data/spec/models/concerns/eventable_spec.rb +20 -0
- data/spec/models/subscriber_spec.rb +64 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/support/active_record.rb +34 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c1ed56da3f6b079d59b295ce74da1cf587ebf593
|
4
|
+
data.tar.gz: 41a58ff5ed78311cbf680b64732be8b4e6ea252d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d8fa857f03b7205b53f8931355c90ec261a43c45f20c5726709f3afa9197a4598c54262724da35cd26004c9da49bd9395ae3563201e2a9080078daf1e73ee4f4
|
7
|
+
data.tar.gz: 50c9fd5ebdb5aa978966ea0f6418b086dd0607dd5c8304c31fc0528198e56a70e1b60947d69af6698dcf909f3804f152f6d34880bff3cdd1cd535e703270780a
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 winfred
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Reactor
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'reactor'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install reactor
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class Reactor::Event
|
2
|
+
include Reactor::OptionallySubclassable
|
3
|
+
|
4
|
+
def self.publish(name, data = {})
|
5
|
+
message = Reactor::Message.new(data.merge(event: name))
|
6
|
+
if (message.at)
|
7
|
+
delay_until(message.at).process name, message.data
|
8
|
+
else
|
9
|
+
delay.process name, message.data
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.reschedule(name, data = {})
|
14
|
+
job = scheduled_jobs.detect do |job|
|
15
|
+
job['class'] == name.to_s.camelize && job['at'].to_i == data[:was].to_i
|
16
|
+
end
|
17
|
+
remove_scheduled_job job if job
|
18
|
+
delay.publish(name, data.except(:was)) if data[:at].future?
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
name
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.process(name, data)
|
26
|
+
Reactor::Subscriber.where(event: name.to_s).each do |subscriber|
|
27
|
+
Reactor::Subscriber.delay.fire subscriber.id, data
|
28
|
+
end
|
29
|
+
|
30
|
+
#TODO: support more matching?
|
31
|
+
Reactor::Subscriber.where(event: '*').each do |s|
|
32
|
+
Reactor::Subscriber.delay.fire s.id, data
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def self.scheduled_jobs(options = {})
|
39
|
+
Sidekiq.redis do |r|
|
40
|
+
from = options[:from] ? options[:from].to_f.to_s : '-inf'
|
41
|
+
to = options[:to] ? options[:to].to_f.to_s : '+inf'
|
42
|
+
r.zrangebyscore('schedule', from, to).map{|job| MultiJson.decode(job)}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.remove_scheduled_job(job)
|
47
|
+
Sidekiq.redis { |r| r.zrem 'schedule', MultiJson.encode(job) }
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Reactor::Message
|
2
|
+
attr_accessor :data
|
3
|
+
|
4
|
+
def initialize(data = {})
|
5
|
+
self.data = {}.with_indifferent_access
|
6
|
+
data.each do |key, value|
|
7
|
+
self.send("#{key}=", value)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method, *args)
|
12
|
+
if method.to_s.include?('=')
|
13
|
+
try_setter(method, *args)
|
14
|
+
else
|
15
|
+
try_getter(method)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def try_setter(method, object, *args)
|
22
|
+
if object.is_a? ActiveRecord::Base
|
23
|
+
send("#{method}_id", object.id)
|
24
|
+
send("#{method}_type", object.class.to_s)
|
25
|
+
else
|
26
|
+
data[method.to_s.gsub('=','')] = object
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def try_getter(method)
|
31
|
+
if polymorphic_association? method
|
32
|
+
initialize_polymorphic_association method
|
33
|
+
elsif data.has_key?(method)
|
34
|
+
data[method]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def polymorphic_association?(method)
|
39
|
+
data.has_key?("#{method}_type")
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize_polymorphic_association(method)
|
43
|
+
data["#{method}_type"].constantize.find(data["#{method}_id"])
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Reactor::Eventable
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
after_create :schedule_events
|
6
|
+
after_update :reschedule_events
|
7
|
+
end
|
8
|
+
|
9
|
+
def publish(name, data = {})
|
10
|
+
Reactor::Event.publish(name, data.merge(actor: self) )
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def publishes(name, data = {})
|
15
|
+
events[name] = data
|
16
|
+
end
|
17
|
+
|
18
|
+
def events
|
19
|
+
@events ||= {}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def schedule_events
|
26
|
+
self.class.events.each do |name, data|
|
27
|
+
Reactor::Event.delay.publish name, data.merge(
|
28
|
+
at: send(data[:at]), actor: self
|
29
|
+
).except(:watch)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def reschedule_events
|
34
|
+
self.class.events.each do |name, data|
|
35
|
+
if send("#{data[:watch] || data[:at]}_changed?")
|
36
|
+
Reactor::Event.delay.reschedule name,
|
37
|
+
at: send(data[:at]),
|
38
|
+
actor: self,
|
39
|
+
was: send("#{data[:at]}_was")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Reactor::Subscriber < ActiveRecord::Base
|
2
|
+
attr_accessible :event
|
3
|
+
attr_accessor :message
|
4
|
+
|
5
|
+
def event=(event)
|
6
|
+
write_attribute :event, event.to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
def fire(data)
|
10
|
+
self.message = Reactor::Message.new(data)
|
11
|
+
instance_exec &self.class.on_fire
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def delay_amount
|
16
|
+
self.class.delay_amount
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def on_fire(&block)
|
21
|
+
if block
|
22
|
+
@fire_block = block
|
23
|
+
end
|
24
|
+
@fire_block
|
25
|
+
end
|
26
|
+
|
27
|
+
def fire(subscriber_id, data)
|
28
|
+
Reactor::Subscriber.find(subscriber_id).fire data
|
29
|
+
end
|
30
|
+
|
31
|
+
def subscribes_to(name = nil, delay: nil)
|
32
|
+
@delay_amount = delay
|
33
|
+
#subscribers << name
|
34
|
+
#TODO: REMEMBER SUBSCRIBERS so we can define them in code as well as with a row in the DB
|
35
|
+
end
|
36
|
+
|
37
|
+
def delay_amount
|
38
|
+
@delay_amount
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
RSpec::Matchers.define :publish_event do |name, data = {}|
|
2
|
+
|
3
|
+
match do |block|
|
4
|
+
if data.empty?
|
5
|
+
Reactor::Event.should_receive(:publish).with do |*args|
|
6
|
+
args.first.should == name
|
7
|
+
end
|
8
|
+
else
|
9
|
+
Reactor::Event.should_receive(:publish).with(name, data)
|
10
|
+
end
|
11
|
+
block.call
|
12
|
+
end
|
13
|
+
end
|
data/lib/reactor.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "reactor/version"
|
2
|
+
require "reactor/models/concerns/eventable"
|
3
|
+
require "reactor/models/concerns/optionally_subclassable"
|
4
|
+
require "reactor/models/subscriber"
|
5
|
+
require "reactor/event"
|
6
|
+
require "reactor/message"
|
7
|
+
|
8
|
+
module Reactor
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
ActiveRecord::Base.send(:include, Reactor::Eventable)
|
data/reactor.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'reactor/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "reactor"
|
8
|
+
spec.version = Reactor::VERSION
|
9
|
+
spec.authors = ["winfred", "walt"]
|
10
|
+
spec.email = ["winfred@developerauction.com", "walt@developerauction.com", "curtis@developerauction.com", "nate@developerauction.com"]
|
11
|
+
spec.description = %q{ rails chrono reactor }
|
12
|
+
spec.summary = %q{ Sidekiq/ActiveRecord pubsub lib }
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
data/spec/event_spec.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Reactor::Event do
|
4
|
+
|
5
|
+
let(:event_name) { :user_did_this }
|
6
|
+
|
7
|
+
describe 'publish' do
|
8
|
+
it 'fires the first process and sets message event_id' do
|
9
|
+
Reactor::Event.should_receive(:process).with(event_name, 'actor_id' => '1', 'event' => :user_did_this)
|
10
|
+
Reactor::Event.publish(:user_did_this, actor_id: '1')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'process' do
|
15
|
+
it 'fires all subscribers' do
|
16
|
+
Reactor::Subscriber.create(event: :user_did_this)
|
17
|
+
Reactor::Subscriber.any_instance.should_receive(:fire).with(actor_id: '1')
|
18
|
+
Reactor::Event.process(event_name, actor_id: '1')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/active_record'
|
3
|
+
|
4
|
+
module MyModule
|
5
|
+
class Pet < ActiveRecord::Base
|
6
|
+
end
|
7
|
+
|
8
|
+
class Cat < Pet
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
class ArbitraryModel < ActiveRecord::Base
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Reactor::Message do
|
17
|
+
let(:cat) { MyModule::Cat.create }
|
18
|
+
let(:arbitrary_model) { ArbitraryModel.create }
|
19
|
+
let(:message_data) { {random: 'data', pet_id: cat.id, pet_type: cat.class.to_s, arbitrary_model: arbitrary_model } }
|
20
|
+
let(:message) { Reactor::Message.new(message_data) }
|
21
|
+
|
22
|
+
describe 'data key fallthrough' do
|
23
|
+
subject { message }
|
24
|
+
|
25
|
+
describe 'getters' do
|
26
|
+
context 'basic key value' do
|
27
|
+
its(:random) { should == 'data' }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'foreign key and foreign type' do
|
31
|
+
its(:pet) { should be_a MyModule::Cat }
|
32
|
+
its('pet.id') { should == MyModule::Cat.last.id }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'setters' do
|
37
|
+
it 'sets simple keys' do
|
38
|
+
message.simple = 'key'
|
39
|
+
message.data[:simple].should == 'key'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'sets active_record polymorphic keys' do
|
43
|
+
message.complex = cat = MyModule::Cat.create
|
44
|
+
message.complex_id = cat.id
|
45
|
+
message.complex_type = cat.class.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'data' do
|
51
|
+
let(:serialized_message) { message.data }
|
52
|
+
specify { serialized_message.should be_a Hash }
|
53
|
+
specify { serialized_message[:random].should == 'data' }
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'new' do
|
57
|
+
specify { message.should be_a Reactor::Message }
|
58
|
+
specify { message.pet_id.should == cat.id }
|
59
|
+
specify { message.arbitrary_model_id.should == arbitrary_model.id }
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Auction < ActiveRecord::Base
|
4
|
+
def ring_timeout(was: false)
|
5
|
+
created_at + (was ? 10.seconds : 30.seconds)
|
6
|
+
end
|
7
|
+
|
8
|
+
publishes :ring, at: :ring_timeout, watch: :name
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Reactor::Eventable do
|
12
|
+
describe 'publish' do
|
13
|
+
let(:auction) { Auction.create }
|
14
|
+
|
15
|
+
it 'publishes an event with actor_id and actor_type set as self' do
|
16
|
+
Reactor::Event.should_receive(:publish).with(:an_event, {what: 'the', actor: auction}).twice
|
17
|
+
auction.publish(:an_event, {what: 'the'})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class MySubscriber < Reactor::Subscriber
|
4
|
+
attr_accessor :was_called
|
5
|
+
|
6
|
+
on_fire do
|
7
|
+
self.was_called = true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Reactor::Subscriber do
|
12
|
+
|
13
|
+
describe 'fire' do
|
14
|
+
subject { MySubscriber.create(event: :you_name_it).fire some: 'random', event: 'data' }
|
15
|
+
|
16
|
+
its(:message) { should be_a Reactor::Message }
|
17
|
+
its('message.some') { should == 'random' }
|
18
|
+
|
19
|
+
it 'executes block given' do
|
20
|
+
subject.was_called.should be_true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '.subscribes_to class helper' do
|
25
|
+
#describe 'ensuring subscriber exists and is tied to event' do
|
26
|
+
# it 'binds 1-1 when name given' do
|
27
|
+
# expect {
|
28
|
+
# MySubscriber.class_eval do
|
29
|
+
# subscribes_to :event_times
|
30
|
+
# end
|
31
|
+
# }.to change { Reactor::Subscriber.count }.by(1)
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# context 'binds to all when star is given' do
|
35
|
+
# after { MySubscriber.destroy_all }
|
36
|
+
#
|
37
|
+
# it 'creates new subscriber' do
|
38
|
+
# expect {
|
39
|
+
# MySubscriber.class_eval do
|
40
|
+
# subscribes_to '*'
|
41
|
+
# end
|
42
|
+
# }.to change { Reactor::Subscriber.count }.by(1)
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# it 'doesnt create' do
|
46
|
+
# MySubscriber.where(event: '*').first_or_create!
|
47
|
+
# expect {
|
48
|
+
# MySubscriber.class_eval do
|
49
|
+
# subscribes_to '*'
|
50
|
+
# end
|
51
|
+
# }.to change { Reactor::Subscriber.count }.by(0)
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
#end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'matcher' do
|
58
|
+
it 'can be set to star to bind to all events' do
|
59
|
+
MySubscriber.create!(event: '*')
|
60
|
+
MySubscriber.any_instance.should_receive(:fire).with({'random' => 'data', 'event' => :this_event})
|
61
|
+
Reactor::Event.publish(:this_event, {random: 'data'})
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
require 'support/active_record'
|
6
|
+
require 'sidekiq'
|
7
|
+
require 'sidekiq/testing/inline'
|
8
|
+
require 'reactor'
|
9
|
+
|
10
|
+
Sidekiq.configure_server do |config|
|
11
|
+
config.redis = { url: ENV["REDISTOGO_URL"] }
|
12
|
+
|
13
|
+
database_url = ENV['DATABASE_URL']
|
14
|
+
if database_url
|
15
|
+
ENV['DATABASE_URL'] = "#{database_url}?pool=25"
|
16
|
+
ActiveRecord::Base.establish_connection
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Sidekiq.configure_client do |config|
|
21
|
+
config.redis = { url: ENV["REDISTOGO_URL"] }
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
RSpec.configure do |config|
|
26
|
+
# some (optional) config here
|
27
|
+
|
28
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
29
|
+
|
30
|
+
# Runs Sidekiq jobs inline by default unless the RSpec metadata :sidekiq is specified,
|
31
|
+
# in which case it will use the real Redis-backed Sidekiq queue
|
32
|
+
config.before(:each, :sidekiq) do
|
33
|
+
Sidekiq.redis{|r| r.flushall }
|
34
|
+
Sidekiq::Client.class_eval do
|
35
|
+
singleton_class.class_eval do
|
36
|
+
alias_method :raw_push, :raw_push_old
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
config.after(:each, :sidekiq) do
|
43
|
+
load "sidekiq/testing/inline.rb"
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
|
4
|
+
|
5
|
+
ActiveRecord::Migrator.up "db/migrate"
|
6
|
+
|
7
|
+
ActiveRecord::Migration.create_table :auctions do |t|
|
8
|
+
t.string :name
|
9
|
+
t.datetime :start_at
|
10
|
+
t.datetime :close_at
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::Migration.create_table :subscribers do |t|
|
16
|
+
t.string :event
|
17
|
+
t.string :type
|
18
|
+
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
|
22
|
+
ActiveRecord::Migration.create_table :pets do |t|
|
23
|
+
t.integer :awesomeness
|
24
|
+
t.string :type
|
25
|
+
|
26
|
+
|
27
|
+
t.timestamps
|
28
|
+
end
|
29
|
+
|
30
|
+
ActiveRecord::Migration.create_table :arbitrary_models do |t|
|
31
|
+
t.integer :awesomeness
|
32
|
+
|
33
|
+
t.timestamps
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: reactor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- winfred
|
8
|
+
- walt
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.3'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.3'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
description: ' rails chrono reactor '
|
57
|
+
email:
|
58
|
+
- winfred@developerauction.com
|
59
|
+
- walt@developerauction.com
|
60
|
+
- curtis@developerauction.com
|
61
|
+
- nate@developerauction.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- lib/reactor.rb
|
72
|
+
- lib/reactor/event.rb
|
73
|
+
- lib/reactor/message.rb
|
74
|
+
- lib/reactor/models/concerns/eventable.rb
|
75
|
+
- lib/reactor/models/concerns/optionally_subclassable.rb
|
76
|
+
- lib/reactor/models/subscriber.rb
|
77
|
+
- lib/reactor/testing/matchers.rb
|
78
|
+
- lib/reactor/version.rb
|
79
|
+
- reactor.gemspec
|
80
|
+
- spec/event_spec.rb
|
81
|
+
- spec/message_spec.rb
|
82
|
+
- spec/models/concerns/eventable_spec.rb
|
83
|
+
- spec/models/subscriber_spec.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
- spec/support/active_record.rb
|
86
|
+
homepage: ''
|
87
|
+
licenses:
|
88
|
+
- MIT
|
89
|
+
metadata: {}
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 2.0.0
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: Sidekiq/ActiveRecord pubsub lib
|
110
|
+
test_files:
|
111
|
+
- spec/event_spec.rb
|
112
|
+
- spec/message_spec.rb
|
113
|
+
- spec/models/concerns/eventable_spec.rb
|
114
|
+
- spec/models/subscriber_spec.rb
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
- spec/support/active_record.rb
|