rumor 0.1.0
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 +17 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +61 -0
- data/Rakefile +1 -0
- data/lib/rumor.rb +30 -0
- data/lib/rumor/async/resque.rb +38 -0
- data/lib/rumor/channel.rb +27 -0
- data/lib/rumor/rumor.rb +119 -0
- data/lib/rumor/source.rb +31 -0
- data/lib/rumor/version.rb +3 -0
- data/rumor.gemspec +26 -0
- data/spec/rumor/channel_spec.rb +49 -0
- data/spec/rumor_spec.rb +72 -0
- data/spec/spec_helper.rb +7 -0
- metadata +161 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Mattias Putman
|
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,61 @@
|
|
1
|
+
# Rumor
|
2
|
+
|
3
|
+
All event processing is done asynchronously. Different adapters can be used to handle the processing (currently only Resque, default).
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
### Let those controllers rumor
|
8
|
+
|
9
|
+
**First**
|
10
|
+
|
11
|
+
Add rumor capabilities to your controller by adding `include Rumor::Source`.
|
12
|
+
|
13
|
+
**Then**
|
14
|
+
|
15
|
+
Add rumor instructions in your controller methods.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
# Rumor about an event.
|
19
|
+
rumor(:upgrade).on('john').mention(plan: plan.id).tag(:important).spread
|
20
|
+
# Rumor only to certain channels.
|
21
|
+
# Rumor whatever you want.
|
22
|
+
rumor(:profit).tag(:finally).spread only: [:mixpanel]
|
23
|
+
```
|
24
|
+
|
25
|
+
**Where does the rumor come from?**
|
26
|
+
|
27
|
+
The `rumor` method is a regular method defined in your controller (defined by including `Source`). You can use it to add default values to your rumors.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class AccountController
|
31
|
+
include Rumor::Source
|
32
|
+
|
33
|
+
def rumor event
|
34
|
+
super(event).on(current_user.id).tag(:accounts)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
### Adding Rumor Channels
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
class MixpanelChannel < Rumor::Channel
|
43
|
+
|
44
|
+
# This is just a regular class.
|
45
|
+
def initialize tracker
|
46
|
+
@tracker = tracker
|
47
|
+
end
|
48
|
+
|
49
|
+
# Matches only upgrade events with the important tag.
|
50
|
+
on(:upgrade) do |rumor|
|
51
|
+
rumor.subject # => 'john'
|
52
|
+
rumor.tag # => [:important]
|
53
|
+
plan = Plan.find rumor.mentions[:plan]
|
54
|
+
@tracker.track 'Upgraded Account', to: plan.name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Register the channel.
|
59
|
+
tracker = Mixpanel::Tracker.new Environment::MIXPANEL_TOKEN,
|
60
|
+
Rumor.register :mixpanel, MixpanelChannel.new tracker
|
61
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/rumor.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "rumor/version"
|
2
|
+
require 'rumor/channel'
|
3
|
+
require 'rumor/rumor'
|
4
|
+
require 'rumor/source'
|
5
|
+
|
6
|
+
module Rumor
|
7
|
+
class << self
|
8
|
+
attr_accessor :channels
|
9
|
+
attr_accessor :async_handler
|
10
|
+
end
|
11
|
+
|
12
|
+
@channels = {}
|
13
|
+
|
14
|
+
# Internal: Register a new channel.
|
15
|
+
def self.register name, channel
|
16
|
+
self.channels[name] = channel
|
17
|
+
end
|
18
|
+
|
19
|
+
# Internal: Spread a rumor to required channels.
|
20
|
+
def self.spread rumor
|
21
|
+
self.channels.each do |name, channel|
|
22
|
+
channel.send rumor if rumor.to?(name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Internal: Spread a rumor asynchronously.
|
27
|
+
def self.spread_async rumor
|
28
|
+
self.async_handler.spread_async rumor
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'resque'
|
2
|
+
|
3
|
+
module Rumor
|
4
|
+
module Async
|
5
|
+
|
6
|
+
class Resque
|
7
|
+
|
8
|
+
def self.spread_async rumor
|
9
|
+
::Resque.enqueue Job, rumor.to_h
|
10
|
+
end
|
11
|
+
|
12
|
+
class Job
|
13
|
+
@queue = :rumor
|
14
|
+
|
15
|
+
def self.perform rumor_hash
|
16
|
+
hash = hash_to_symbols rumor_hash
|
17
|
+
hash[:mentions] = hash_to_symbols hash[:mentions]
|
18
|
+
hash[:tags].map! &:to_sym
|
19
|
+
hash[:time] = Time.new hash[:time]
|
20
|
+
# Deserialize the rumor.
|
21
|
+
rumor = Rumor.from_h hash
|
22
|
+
# Spread again.
|
23
|
+
::Rumor.spread rumor
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.hash_to_symbols hash
|
27
|
+
symbol_hash = {}
|
28
|
+
hash.each do |k,v|
|
29
|
+
symbol_hash[k.to_sym] = v
|
30
|
+
end
|
31
|
+
symbol_hash
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Rumor.async_handler = Rumor::Async::Resque
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rumor
|
2
|
+
|
3
|
+
# Public: A Channel is a module that can be included in any class.
|
4
|
+
#
|
5
|
+
# It provides an 'on' method for matching rumors by event.
|
6
|
+
class Channel
|
7
|
+
class << self
|
8
|
+
attr_accessor :handlers
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.inherited klass
|
12
|
+
klass.handlers = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# Internal: Send a Rumor to this channel.
|
16
|
+
def send rumor
|
17
|
+
handle = self.class.handlers[rumor.event.to_sym]
|
18
|
+
raise "No handler for event #{rumor.event}" unless handle
|
19
|
+
self.instance_exec rumor, &handle
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: Catch all events with specified name.
|
23
|
+
def self.on event, &handle
|
24
|
+
self.handlers[event] = handle
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/rumor/rumor.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
module Rumor
|
2
|
+
|
3
|
+
# Public: A Rumor represents some knowledge about
|
4
|
+
# something that can be spread.
|
5
|
+
#
|
6
|
+
# Examples
|
7
|
+
#
|
8
|
+
# Rumor.new(:upgraded).on('user1').mention(plan: :tasty).tag(:business).spread
|
9
|
+
#
|
10
|
+
class Rumor
|
11
|
+
|
12
|
+
# Public: A rumor has an event name.
|
13
|
+
# this is required for every rumor.
|
14
|
+
attr_accessor :event
|
15
|
+
|
16
|
+
# Public: Wo the rumor is about
|
17
|
+
# This is mostly the user that executed the event.
|
18
|
+
attr_accessor :subject
|
19
|
+
|
20
|
+
# Public: The mentions of the rumor.
|
21
|
+
# All the information a rumor mentions.
|
22
|
+
attr_accessor :mentions
|
23
|
+
|
24
|
+
# Public: Every rumor has some tags.
|
25
|
+
# A Rumor can be categorized in multiple optional tags.
|
26
|
+
attr_accessor :tags
|
27
|
+
|
28
|
+
# Public: Create Rumor from hash.
|
29
|
+
def self.from_h hash
|
30
|
+
self.new(hash[:event], hash[:time]).
|
31
|
+
mention(hash[:mentions]).
|
32
|
+
on(hash[:subject]).
|
33
|
+
tag(*hash[:tags])
|
34
|
+
end
|
35
|
+
|
36
|
+
# Public: Creates a new rumor.
|
37
|
+
#
|
38
|
+
# event - event of the rumor.
|
39
|
+
def initialize event, time = nil
|
40
|
+
@event = event
|
41
|
+
@tags = []
|
42
|
+
@mentions = {}
|
43
|
+
@time = time
|
44
|
+
end
|
45
|
+
|
46
|
+
# Public: Tell who/what the rumor is concerning.
|
47
|
+
def on subject
|
48
|
+
@subject = subject
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
# Public: Mention some things in the rumor.
|
53
|
+
# Merges with already mentioned information.
|
54
|
+
def mention mentions = {}
|
55
|
+
@mentions.merge!(mentions) do |key, old_val, new_val|
|
56
|
+
if old.kind_of?(Array)
|
57
|
+
old_val + new_val
|
58
|
+
elsif old.kind_of?(Hash)
|
59
|
+
old_val.merge new_val
|
60
|
+
else
|
61
|
+
new_val
|
62
|
+
end
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
# Public: Add some tags to the rumor.
|
68
|
+
def tag *tags
|
69
|
+
@tags += tags
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
# Public: Copy a rumor while altering information.
|
74
|
+
def copy &alter
|
75
|
+
Rumor.new(hash).tap &alter
|
76
|
+
end
|
77
|
+
|
78
|
+
# Spread the rumor to all applicable channels.
|
79
|
+
#
|
80
|
+
# conditions - some conditions on the spreading (Hash).
|
81
|
+
# :only - The channels to spread to (and none other).
|
82
|
+
# :except - The channels not to spread to.
|
83
|
+
#
|
84
|
+
# Returns nothing.
|
85
|
+
def spread conditions = {}
|
86
|
+
@time = Time.now.utc
|
87
|
+
@only = conditions[:only]
|
88
|
+
@except = conditions[:except]
|
89
|
+
::Rumor.spread_async self
|
90
|
+
end
|
91
|
+
|
92
|
+
# Public: The time the rumor was spread.
|
93
|
+
def time
|
94
|
+
@time
|
95
|
+
end
|
96
|
+
|
97
|
+
# Public: Whether to send this rumor to the given channel.
|
98
|
+
#
|
99
|
+
# channel - Name of the channel.
|
100
|
+
def to? channel
|
101
|
+
(!@only && !@except) ||
|
102
|
+
(@only && @only.include?(channel)) ||
|
103
|
+
(@except && !@except.include?(channel))
|
104
|
+
end
|
105
|
+
|
106
|
+
# Public: Rumor in hash form.
|
107
|
+
#
|
108
|
+
# Returns the rumor converted to a Hash.
|
109
|
+
def to_h
|
110
|
+
{
|
111
|
+
event: event,
|
112
|
+
subject: subject,
|
113
|
+
mentions: mentions,
|
114
|
+
tags: tags,
|
115
|
+
time: time
|
116
|
+
}
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/rumor/source.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Rumor
|
2
|
+
|
3
|
+
# Public: Include this module everywhere you want to be
|
4
|
+
# able to rumor. This gives you the benefit that the rumor
|
5
|
+
# method can easily be overrided.
|
6
|
+
#
|
7
|
+
# Exampe:
|
8
|
+
#
|
9
|
+
# class Controller
|
10
|
+
# include Rumor::Rumoring
|
11
|
+
#
|
12
|
+
# def rumor subject
|
13
|
+
# super.on(current_user)
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# def upgrade
|
17
|
+
# # some code
|
18
|
+
# rumor(:upgraded).mention(plan: :basic).spread only: :kissmetrics
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
module Source
|
23
|
+
|
24
|
+
# Public: Acts as a specialized factory for rumors.
|
25
|
+
#
|
26
|
+
# Returns a new Rumor.
|
27
|
+
def rumor event
|
28
|
+
Rumor.new(event)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/rumor.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rumor/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "rumor"
|
8
|
+
gem.version = Rumor::VERSION
|
9
|
+
gem.authors = ["Mattias Putman"]
|
10
|
+
gem.email = ["mattias.putman@gmail.com"]
|
11
|
+
gem.description = %q{Rumor}
|
12
|
+
gem.summary = %q{Rumor}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency 'resque'
|
21
|
+
gem.add_development_dependency 'rake'
|
22
|
+
gem.add_development_dependency 'guard'
|
23
|
+
gem.add_development_dependency 'guard-minitest'
|
24
|
+
gem.add_development_dependency 'mocha'
|
25
|
+
gem.add_development_dependency 'rb-fsevent', '~> 0.9'
|
26
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestChannel < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
class ExampleChannel < Rumor::Channel
|
6
|
+
def helper
|
7
|
+
"helper"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@channel = ExampleChannel.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_define_handler
|
16
|
+
assert_equal ExampleChannel.handlers, {}
|
17
|
+
handle = proc {}
|
18
|
+
ExampleChannel.on(:upgrade, &handle)
|
19
|
+
assert_equal ExampleChannel.handlers[:upgrade], handle
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_send_rumor
|
23
|
+
upgrade = proc {}
|
24
|
+
install = proc { |rumor| @rumor = rumor }
|
25
|
+
ExampleChannel.on(:upgrade, &upgrade)
|
26
|
+
ExampleChannel.on(:install, &install)
|
27
|
+
|
28
|
+
@channel.send Rumor::Rumor.new(:install).
|
29
|
+
tag(:business).
|
30
|
+
on(:cool_user).
|
31
|
+
mention(plan: :enterprise)
|
32
|
+
|
33
|
+
rumor = @channel.instance_variable_get :@rumor
|
34
|
+
assert rumor.event == :install && rumor.tags == [:business] &&
|
35
|
+
rumor.mentions == { plan: :enterprise } && rumor.subject == :cool_user
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_use_methods
|
39
|
+
ExampleChannel.on(:method_test) do |rumor|
|
40
|
+
helper
|
41
|
+
end
|
42
|
+
@channel.expects(:helper).once
|
43
|
+
@channel.send Rumor::Rumor.new(:method_test)
|
44
|
+
end
|
45
|
+
|
46
|
+
def teardown
|
47
|
+
ExampleChannel.handlers = {}
|
48
|
+
end
|
49
|
+
end
|
data/spec/rumor_spec.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestRumor < MiniTest::Unit::TestCase
|
4
|
+
include Rumor::Source
|
5
|
+
|
6
|
+
class ExampleChannel < Rumor::Channel
|
7
|
+
end
|
8
|
+
|
9
|
+
class IntegrationChannel < Rumor::Channel
|
10
|
+
def initialize delegate
|
11
|
+
@delegate = delegate
|
12
|
+
end
|
13
|
+
|
14
|
+
on(:upgrade) do |rumor|
|
15
|
+
@delegate.upgrade
|
16
|
+
end
|
17
|
+
|
18
|
+
on(:install) do |rumor|
|
19
|
+
@delegate.install
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup
|
24
|
+
@channel = ExampleChannel.new
|
25
|
+
@rumor = Rumor::Rumor.new(:upgrade).mention price: 8
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_channels_initialized
|
29
|
+
assert_equal Rumor.channels, {}
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_add_channel
|
33
|
+
Rumor.register :example, @channel
|
34
|
+
assert_equal Rumor.channels[:example], @channel
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_spread_both
|
38
|
+
left, right = ExampleChannel.new, ExampleChannel.new
|
39
|
+
Rumor.register :left, left
|
40
|
+
Rumor.register :right, right
|
41
|
+
left.expects(:send).with(@rumor).once
|
42
|
+
right.expects(:send).with(@rumor).once
|
43
|
+
Rumor.spread @rumor
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_spread_filter
|
47
|
+
left, right = ExampleChannel.new, ExampleChannel.new
|
48
|
+
@rumor.stubs(:to?).with(:left).returns true
|
49
|
+
@rumor.stubs(:to?).with(:right).returns false
|
50
|
+
Rumor.register :left, left
|
51
|
+
Rumor.register :right, right
|
52
|
+
left.expects(:send).with(@rumor).once
|
53
|
+
right.expects(:send).with(@rumor).never
|
54
|
+
Rumor.spread @rumor
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_spread_async
|
58
|
+
Rumor::Async::Resque.expects(:spread_async).with(@rumor).once
|
59
|
+
Rumor.spread_async @rumor
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_integration
|
63
|
+
channel1 = mock
|
64
|
+
Rumor.register :channel1, IntegrationChannel.new(channel1)
|
65
|
+
channel1.expects(:upgrade)
|
66
|
+
rumor(:upgrade).mention(plan: :enterprise).spread
|
67
|
+
end
|
68
|
+
|
69
|
+
def teardown
|
70
|
+
Rumor.channels = {}
|
71
|
+
end
|
72
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rumor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mattias Putman
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: resque
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: guard
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: guard-minitest
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: mocha
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rb-fsevent
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.9'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.9'
|
110
|
+
description: Rumor
|
111
|
+
email:
|
112
|
+
- mattias.putman@gmail.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- Gemfile
|
119
|
+
- Guardfile
|
120
|
+
- LICENSE.txt
|
121
|
+
- README.md
|
122
|
+
- Rakefile
|
123
|
+
- lib/rumor.rb
|
124
|
+
- lib/rumor/async/resque.rb
|
125
|
+
- lib/rumor/channel.rb
|
126
|
+
- lib/rumor/rumor.rb
|
127
|
+
- lib/rumor/source.rb
|
128
|
+
- lib/rumor/version.rb
|
129
|
+
- rumor.gemspec
|
130
|
+
- spec/rumor/channel_spec.rb
|
131
|
+
- spec/rumor_spec.rb
|
132
|
+
- spec/spec_helper.rb
|
133
|
+
homepage: ''
|
134
|
+
licenses: []
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
none: false
|
141
|
+
requirements:
|
142
|
+
- - ! '>='
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
none: false
|
147
|
+
requirements:
|
148
|
+
- - ! '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 1.8.19
|
154
|
+
signing_key:
|
155
|
+
specification_version: 3
|
156
|
+
summary: Rumor
|
157
|
+
test_files:
|
158
|
+
- spec/rumor/channel_spec.rb
|
159
|
+
- spec/rumor_spec.rb
|
160
|
+
- spec/spec_helper.rb
|
161
|
+
has_rdoc:
|