ventable 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/Guardfile +15 -0
- data/LICENSE +22 -0
- data/README.md +116 -0
- data/Rakefile +3 -0
- data/lib/ventable.rb +15 -0
- data/lib/ventable/event.rb +86 -0
- data/lib/ventable/version.rb +3 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/ventable/ventable_spec.rb +169 -0
- data/ventable.gemspec +22 -0
- metadata +110 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#^syntax detection
|
3
|
+
|
4
|
+
# A sample Guardfile
|
5
|
+
# More info at https://github.com/guard/guard#readme
|
6
|
+
|
7
|
+
guard 'rspec' do
|
8
|
+
watch(%r{^ventable\.gemspec}) { "spec"}
|
9
|
+
watch(%r{^lib/(.+)\.rb$}) { "spec" }
|
10
|
+
|
11
|
+
watch(%r{^spec/.+_spec\.rb$})
|
12
|
+
watch('spec/spec_helper.rb') { "spec" }
|
13
|
+
watch(%r{spec/support/.*}) { "spec" }
|
14
|
+
end
|
15
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Konstantin Gredeskoul
|
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,116 @@
|
|
1
|
+
[![Build status](https://secure.travis-ci.org/kigster/ventable.png)](http://travis-ci.org/kigster/ventable)
|
2
|
+
|
3
|
+
# Ventable
|
4
|
+
|
5
|
+
Simple eventing gem that implements Observable pattern, but with more options, ability to group observers and wrap
|
6
|
+
them in arbitrary blocks of code. For example, when a certain event fires, some observers may be called within
|
7
|
+
a transaction context, while others maybe called outside of the transaction context.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'ventable'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install ventable
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
1. Create your own plain ruby class that optionally carries some data important to the event. Include module Ventable::Event.
|
26
|
+
2. Create one or more observers. Observer can be any class that implements event handler method as a class method, such as a
|
27
|
+
generic method ```self.handle_event(event)``` or a more specific method mapped to the event name: say for event UserRegistered the
|
28
|
+
callback event would be ```self.handle_user_registered_event(event)```
|
29
|
+
3. Register your observers with the event using ```notifies``` event method, or register groups using ```group``` method, and then
|
30
|
+
use ```notify``` with options ```inside: :group_name```
|
31
|
+
4. Instantiate your event (optionally with data), and call fire!() method.
|
32
|
+
|
33
|
+
## Example
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'ventable'
|
37
|
+
|
38
|
+
# this is a custom Event class that has some data associated with it
|
39
|
+
|
40
|
+
class AlarmSoundEvent
|
41
|
+
include Ventable::Event
|
42
|
+
attr_accessor :wakeup_time
|
43
|
+
|
44
|
+
def initialize(wakeup_time)
|
45
|
+
@wakeup_time = wakeup_time
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# This class is an observer, interested in WakeUpEvents.
|
50
|
+
class SleepingPerson
|
51
|
+
def self.handle_wake_up_event(event)
|
52
|
+
self.wake_up
|
53
|
+
puts "snoozing at #{event.wakeup_time}"
|
54
|
+
self.snooze(5)
|
55
|
+
end
|
56
|
+
#.. implementation
|
57
|
+
end
|
58
|
+
|
59
|
+
# Register the observer
|
60
|
+
AlarmSoundEvent.notifies SleepingPerson
|
61
|
+
|
62
|
+
# Create and fire the event
|
63
|
+
AlarmSoundEvent.new(Date.new).fire!
|
64
|
+
```
|
65
|
+
|
66
|
+
## Using #configure and groups
|
67
|
+
|
68
|
+
|
69
|
+
Events can be configured to call observers in groups, with an optional block around it.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
|
73
|
+
transaction = ->(b){
|
74
|
+
ActiveRecord::Base.transaction do
|
75
|
+
b.call
|
76
|
+
end
|
77
|
+
}
|
78
|
+
|
79
|
+
class SomeEvent
|
80
|
+
include Ventable::Event
|
81
|
+
end
|
82
|
+
|
83
|
+
SomeEvent.configure do
|
84
|
+
# first observer to be called
|
85
|
+
notifies FirstObserverClassToBeCalled
|
86
|
+
|
87
|
+
# this group will be notified next
|
88
|
+
group :transaction, &transaction
|
89
|
+
|
90
|
+
# this block is executed after the group
|
91
|
+
notifies inside: :transaction do
|
92
|
+
# perform block
|
93
|
+
end
|
94
|
+
|
95
|
+
# these observers are run inside the transaction block
|
96
|
+
notifies ObserverClass1, ObserverClass2, inside: :transaction
|
97
|
+
|
98
|
+
# this one is the last to be notified
|
99
|
+
notifies AnotherObserverClass
|
100
|
+
end
|
101
|
+
|
102
|
+
SomeEvent.new.fire!
|
103
|
+
|
104
|
+
```
|
105
|
+
|
106
|
+
## Contributing
|
107
|
+
|
108
|
+
1. Fork it
|
109
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
110
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
111
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
112
|
+
5. Create new Pull Request
|
113
|
+
|
114
|
+
## Author
|
115
|
+
|
116
|
+
Konstantin Gredeskoul, @kig, http://github.com/kigster
|
data/Rakefile
ADDED
data/lib/ventable.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "ventable/version"
|
2
|
+
require "ventable/event"
|
3
|
+
|
4
|
+
module Ventable
|
5
|
+
end
|
6
|
+
|
7
|
+
class String
|
8
|
+
def underscore
|
9
|
+
self.gsub(/::/, '/').
|
10
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
11
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
12
|
+
tr("-", "_").
|
13
|
+
downcase
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module ::Ventable
|
4
|
+
module Event
|
5
|
+
def self.included(klazz)
|
6
|
+
klazz.instance_eval do
|
7
|
+
@observers = Set.new
|
8
|
+
class << self
|
9
|
+
attr_accessor :observers
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
klazz.extend ClassMethods
|
14
|
+
end
|
15
|
+
|
16
|
+
def fire!
|
17
|
+
notify_observer_set(self.class.observers)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def notify_observer_set(observer_set)
|
23
|
+
observer_set.each do |observer_entry|
|
24
|
+
if observer_entry.is_a?(Hash)
|
25
|
+
around_block = observer_entry[:around_block]
|
26
|
+
inside_block = -> { notify_observer_set(observer_entry[:observers]) }
|
27
|
+
around_block.call(inside_block)
|
28
|
+
else
|
29
|
+
notify_observer(observer_entry)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def notify_observer(observer)
|
35
|
+
case observer
|
36
|
+
when Proc
|
37
|
+
observer.call(self)
|
38
|
+
else # class
|
39
|
+
notify_class_observer(observer)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def notify_class_observer(observer)
|
44
|
+
observer.respond_to?(self.class.default_callback_method) ?
|
45
|
+
observer.send(self.class.default_callback_method, self) :
|
46
|
+
observer.send(:handle_event, self)
|
47
|
+
end
|
48
|
+
|
49
|
+
module ClassMethods
|
50
|
+
def configure(&block)
|
51
|
+
class_eval(&block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def notifies(*observer_list, &block)
|
55
|
+
options = {}
|
56
|
+
options.merge! observer_list.pop if observer_list.last.is_a?(Hash)
|
57
|
+
observer_set = self.observers
|
58
|
+
if options[:inside]
|
59
|
+
observer_entry = self.find_observer_group(options[:inside])
|
60
|
+
observer_set = observer_entry[:observers]
|
61
|
+
end
|
62
|
+
observer_list.each { |o| observer_set << o } unless observer_list.empty?
|
63
|
+
observer_set << block if block
|
64
|
+
end
|
65
|
+
|
66
|
+
def group(name, &block)
|
67
|
+
raise "Group #{name} already defined by #{g}" if find_observer_group(name)
|
68
|
+
self.observers <<
|
69
|
+
{ name: name,
|
70
|
+
around_block: block,
|
71
|
+
observers: Set.new
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def find_observer_group(name)
|
76
|
+
self.observers.find { |o| o.is_a?(Hash) && o[:name] == name }
|
77
|
+
end
|
78
|
+
|
79
|
+
def default_callback_method
|
80
|
+
target = self
|
81
|
+
method = "handle_" + target.name.gsub(/.*::/,'').underscore.gsub(/_event/, '') + "_event"
|
82
|
+
method.to_sym
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
9
|
+
require 'rubygems'
|
10
|
+
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
11
|
+
require 'ventable'
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
15
|
+
config.run_all_when_everything_filtered = true
|
16
|
+
config.filter_run :focus
|
17
|
+
|
18
|
+
# Run specs in random order to surface order dependencies. If you find an
|
19
|
+
# order dependency and want to debug it, you can fix the order by providing
|
20
|
+
# the seed, which is printed after each run.
|
21
|
+
# --seed 1234
|
22
|
+
config.order = 'random'
|
23
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'ventable'
|
2
|
+
require 'pp'
|
3
|
+
describe Ventable do
|
4
|
+
before do
|
5
|
+
class TestEvent
|
6
|
+
include Ventable::Event
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "including Ventable::Event" do
|
11
|
+
it "should create a class instance variable to keep observers" do
|
12
|
+
TestEvent.observers.should_not be_nil
|
13
|
+
TestEvent.observers.should be_a(Set)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should see observers variable from instance methods" do
|
17
|
+
observers = nil
|
18
|
+
TestEvent.new.instance_eval do
|
19
|
+
observers = self.class.observers
|
20
|
+
end
|
21
|
+
observers.should_not be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should maintain separate sets of observers for each event" do
|
25
|
+
class AnotherEvent
|
26
|
+
include Ventable::Event
|
27
|
+
end
|
28
|
+
AnotherEvent.observers.object_id.should_not == TestEvent.observers.object_id
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#fire" do
|
33
|
+
before do
|
34
|
+
class TestEvent
|
35
|
+
include Ventable::Event
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should properly call a Proc observer" do
|
40
|
+
run_block = false
|
41
|
+
event = nil
|
42
|
+
TestEvent.notifies do |e|
|
43
|
+
run_block = true
|
44
|
+
event = e
|
45
|
+
end
|
46
|
+
run_block.should_not be_true
|
47
|
+
event.should be_nil
|
48
|
+
|
49
|
+
# fire the event
|
50
|
+
TestEvent.new.fire!
|
51
|
+
|
52
|
+
run_block.should be_true
|
53
|
+
event.should_not be_nil
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should properly call a class observer" do
|
57
|
+
TestEvent.instance_eval do
|
58
|
+
class << self
|
59
|
+
attr_accessor :flag
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
TestEvent.class_eval do
|
64
|
+
def set_flag!
|
65
|
+
self.class.flag = true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
class TestEventObserver
|
69
|
+
def self.handle_test_event event
|
70
|
+
event.set_flag!
|
71
|
+
end
|
72
|
+
end
|
73
|
+
TestEvent.notifies TestEventObserver
|
74
|
+
TestEvent.flag.should be_false
|
75
|
+
|
76
|
+
TestEvent.new.fire!
|
77
|
+
TestEvent.flag.should be_true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should properly call a group of observers" do
|
81
|
+
transaction_called = false
|
82
|
+
transaction_completed = false
|
83
|
+
transaction = ->(observer_block) {
|
84
|
+
transaction_called = true
|
85
|
+
observer_block.call
|
86
|
+
transaction_completed = true
|
87
|
+
}
|
88
|
+
|
89
|
+
TestEvent.group :transaction, &transaction
|
90
|
+
observer_block_called = false
|
91
|
+
|
92
|
+
# this flag ensures that this block really runs inside
|
93
|
+
# the transaction group block
|
94
|
+
transaction_already_completed = false
|
95
|
+
event_inside = nil
|
96
|
+
TestEvent.notifies inside: :transaction do |event|
|
97
|
+
observer_block_called = true
|
98
|
+
transaction_already_completed = transaction_completed
|
99
|
+
event_inside = event
|
100
|
+
end
|
101
|
+
|
102
|
+
transaction_called.should be_false
|
103
|
+
transaction_already_completed.should be_false
|
104
|
+
observer_block_called.should be_false
|
105
|
+
|
106
|
+
TestEvent.new.fire!
|
107
|
+
|
108
|
+
transaction_called.should be_true
|
109
|
+
observer_block_called.should be_true
|
110
|
+
transaction_already_completed.should be_false
|
111
|
+
event_inside.should_not be_nil
|
112
|
+
event_inside.should be_a(TestEvent)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#default_callback_method" do
|
117
|
+
before do
|
118
|
+
class SomeAwesomeEvent
|
119
|
+
include Ventable::Event
|
120
|
+
end
|
121
|
+
|
122
|
+
module Blah
|
123
|
+
class AnotherSweetEvent
|
124
|
+
include Ventable::Event
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class SomeOtherStuffHappened
|
129
|
+
include Ventable::Event
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should properly set the callback method name" do
|
134
|
+
SomeAwesomeEvent.default_callback_method.should == :handle_some_awesome_event
|
135
|
+
Blah::AnotherSweetEvent.default_callback_method.should == :handle_another_sweet_event
|
136
|
+
SomeOtherStuffHappened.default_callback_method.should == :handle_some_other_stuff_happened_event
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "#configure" do
|
141
|
+
it "properly configures the event with observesrs" do
|
142
|
+
notified_observer = false
|
143
|
+
TestEvent.configure do
|
144
|
+
notifies do
|
145
|
+
notified_observer = true
|
146
|
+
end
|
147
|
+
end
|
148
|
+
TestEvent.new.fire!
|
149
|
+
notified_observer.should be_true
|
150
|
+
end
|
151
|
+
|
152
|
+
it "configures observers with groups" do
|
153
|
+
notified_observer = false
|
154
|
+
called_transaction = false
|
155
|
+
TestEvent.configure do
|
156
|
+
group :transaction, &->(b){
|
157
|
+
b.call
|
158
|
+
called_transaction = true
|
159
|
+
}
|
160
|
+
notifies inside: :transaction do
|
161
|
+
notified_observer = true
|
162
|
+
end
|
163
|
+
end
|
164
|
+
TestEvent.new.fire!
|
165
|
+
notified_observer.should be_true
|
166
|
+
called_transaction.should be_true
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
data/ventable.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
require File.expand_path('../lib/ventable/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.authors = ["Konstantin Gredeskoul"]
|
7
|
+
gem.email = ["kigster@gmail.com"]
|
8
|
+
gem.description = %q{Event/Observable design pattern in ruby}
|
9
|
+
gem.summary = %q{Event/Observable design pattern in ruby}
|
10
|
+
gem.homepage = "https://github.com/kigster/ventable"
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "ventable"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = Ventable::VERSION
|
18
|
+
|
19
|
+
gem.add_development_dependency "rspec"
|
20
|
+
gem.add_development_dependency "rspec-mocks"
|
21
|
+
gem.add_development_dependency 'guard-rspec'
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ventable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Konstantin Gredeskoul
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
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: rspec-mocks
|
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-rspec
|
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
|
+
description: Event/Observable design pattern in ruby
|
63
|
+
email:
|
64
|
+
- kigster@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- .rspec
|
71
|
+
- .travis.yml
|
72
|
+
- Gemfile
|
73
|
+
- Guardfile
|
74
|
+
- LICENSE
|
75
|
+
- README.md
|
76
|
+
- Rakefile
|
77
|
+
- lib/ventable.rb
|
78
|
+
- lib/ventable/event.rb
|
79
|
+
- lib/ventable/version.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
- spec/ventable/ventable_spec.rb
|
82
|
+
- ventable.gemspec
|
83
|
+
homepage: https://github.com/kigster/ventable
|
84
|
+
licenses: []
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 1.8.24
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: Event/Observable design pattern in ruby
|
107
|
+
test_files:
|
108
|
+
- spec/spec_helper.rb
|
109
|
+
- spec/ventable/ventable_spec.rb
|
110
|
+
has_rdoc:
|