event_hooks 0.0.2 → 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/README.md +18 -1
- data/event_hooks.gemspec +2 -0
- data/lib/event_hooks/event_hooks.rb +28 -0
- data/lib/event_hooks/version.rb +1 -1
- data/spec/database.yml +3 -0
- data/spec/event_hooks/event_hooks_spec.rb +99 -27
- data/spec/hook.sqlite3.db +0 -0
- data/spec/schema.rb +5 -0
- data/spec/spec_helper.rb +7 -0
- metadata +40 -2
data/README.md
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
# EventHooks
|
2
2
|
|
3
|
-
EventHooks enhances
|
3
|
+
EventHooks enhances
|
4
|
+
* Ruby classes to allow adding pre-conditions to method calls (events).
|
5
|
+
* ActiveRecord::Base subclasses to allow adding post-conditions to methods calls.
|
6
|
+
|
4
7
|
If the pre-conditions method returns false the event method will not run. It can be used on ActiveRecord subclasses to validate some conditions only when a certain event occurs.
|
5
8
|
|
9
|
+
If the post-conditions method returns false the database operations triggered by the event will be rolled back. Again, it can be used to validate some conditions after a certain event occurs.
|
10
|
+
|
6
11
|
## Installation
|
7
12
|
|
8
13
|
Add this line to your application's Gemfile:
|
@@ -28,16 +33,28 @@ where:
|
|
28
33
|
* event is the name of a method that you must define prior to the hook_before.
|
29
34
|
* hook is the name of a method that will be run before the call to event.
|
30
35
|
|
36
|
+
or to hook a post-condition
|
37
|
+
```ruby
|
38
|
+
hook_after :event, :hook
|
39
|
+
```
|
40
|
+
|
41
|
+
An example:
|
42
|
+
|
31
43
|
```ruby
|
32
44
|
class AnyClass
|
33
45
|
def submit
|
34
46
|
# do something
|
35
47
|
end
|
36
48
|
hook_before :submit, :submit_preconditions
|
49
|
+
hook_after :submit, :submit_postconditions
|
37
50
|
|
38
51
|
def submit_preconditions
|
39
52
|
am_i_ready?
|
40
53
|
end
|
54
|
+
|
55
|
+
def submit_postconditions
|
56
|
+
am_i_ready?
|
57
|
+
end
|
41
58
|
end
|
42
59
|
```
|
43
60
|
|
data/event_hooks.gemspec
CHANGED
@@ -13,6 +13,8 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.homepage = ""
|
14
14
|
|
15
15
|
gem.add_development_dependency "rspec", "~> 2.12.0"
|
16
|
+
gem.add_development_dependency "activerecord"
|
17
|
+
gem.add_development_dependency "sqlite3"
|
16
18
|
|
17
19
|
gem.files = `git ls-files`.split($/)
|
18
20
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
1
3
|
module EventHooks
|
2
4
|
def self.included(base) #:nodoc:
|
3
5
|
#base.extend EventHooks::ClassMethods
|
@@ -19,4 +21,30 @@ module EventHooks
|
|
19
21
|
end
|
20
22
|
|
21
23
|
Class.send(:include, EventHooks)
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
# make sure hook_after method must be injected in subclasses
|
27
|
+
def inherited(klass)
|
28
|
+
klass.send(:extend, EventHooks::ClassMethods)
|
29
|
+
end
|
30
|
+
|
31
|
+
def hook_after(event, hook)
|
32
|
+
alias_method "#{event}_without_after_hook".to_sym, event
|
33
|
+
|
34
|
+
define_method "#{event}_with_after_hook".to_sym do |*args|
|
35
|
+
ActiveRecord::Base.transaction do
|
36
|
+
res = send("#{event}_without_after_hook".to_sym, *args)
|
37
|
+
unless send(hook)
|
38
|
+
raise ActiveRecord::Rollback, "After_hook #{hook} failed"
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
res
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method event, "#{event}_with_after_hook".to_sym
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
ActiveRecord::Base.send(:extend, EventHooks::ClassMethods)
|
22
50
|
end
|
data/lib/event_hooks/version.rb
CHANGED
data/spec/database.yml
ADDED
@@ -1,5 +1,9 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'logger'
|
1
3
|
require 'spec_helper'
|
2
4
|
|
5
|
+
load_schema
|
6
|
+
|
3
7
|
class StateMachine
|
4
8
|
attr_accessor :ready, :submitted
|
5
9
|
|
@@ -9,7 +13,6 @@ class StateMachine
|
|
9
13
|
end
|
10
14
|
|
11
15
|
def submit
|
12
|
-
puts "SUBMIT NOW"
|
13
16
|
@submitted = true
|
14
17
|
end
|
15
18
|
|
@@ -21,48 +24,117 @@ class StateMachine
|
|
21
24
|
end
|
22
25
|
|
23
26
|
describe "any class" do
|
24
|
-
class
|
27
|
+
class Bar; end
|
25
28
|
|
26
29
|
it "responds to hook_before" do
|
27
|
-
|
30
|
+
Bar.should respond_to(:hook_before)
|
28
31
|
end
|
29
|
-
end
|
30
32
|
|
31
|
-
describe 'hook_before' do
|
32
|
-
|
33
|
+
describe 'hook_before' do
|
34
|
+
let(:sm) { StateMachine.new }
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
sm.submit
|
37
|
-
end
|
38
|
-
|
39
|
-
context "when precondition is met (hook returns true)" do
|
40
|
-
it "allows the event to occur" do
|
41
|
-
sm.should_receive(:submit_without_before_hook).and_call_original
|
36
|
+
it "calls the hook before sending the event" do
|
37
|
+
sm.should_receive(:submission_preconditions)
|
42
38
|
sm.submit
|
43
|
-
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when precondition is met (hook returns true)" do
|
42
|
+
it "allows the event to occur" do
|
43
|
+
sm.should_receive(:submit_without_before_hook).and_call_original
|
44
|
+
sm.submit
|
45
|
+
sm.submitted.should be_true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when precondition is not met (hook returns false)" do
|
50
|
+
let(:sm) { StateMachine.new(false) }
|
51
|
+
|
52
|
+
it "stops the event from happening" do
|
53
|
+
sm.should_receive(:submit_without_before_hook).never
|
54
|
+
sm.submit
|
55
|
+
sm.submitted.should be_false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when you try to add another before hook" do
|
60
|
+
class StateMachine
|
61
|
+
def another_hook
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "raises a DoubleHook exception" do
|
66
|
+
expect { StateMachine.send :hook_before, :submit, :another_hook }.
|
67
|
+
to raise_exception(EventHooks::DoubleHook)
|
68
|
+
end
|
44
69
|
end
|
45
70
|
end
|
71
|
+
end
|
46
72
|
|
47
|
-
|
48
|
-
|
73
|
+
describe "ActiveRecord::Base" do
|
74
|
+
it "responds to hook_after" do
|
75
|
+
ActiveRecord::Base.should respond_to(:hook_after)
|
76
|
+
end
|
77
|
+
end
|
49
78
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
79
|
+
describe "any ActiveRecord::Base subclass" do
|
80
|
+
class Foo < ActiveRecord::Base
|
81
|
+
attr_accessor :ready
|
82
|
+
|
83
|
+
after_initialize do |object|
|
84
|
+
object.ready = true
|
54
85
|
end
|
86
|
+
|
87
|
+
def submit
|
88
|
+
save
|
89
|
+
"SUBMITTED"
|
90
|
+
end
|
91
|
+
|
92
|
+
def submission_postconditions
|
93
|
+
@ready
|
94
|
+
end
|
95
|
+
|
96
|
+
hook_after :submit, :submission_postconditions
|
97
|
+
end
|
98
|
+
|
99
|
+
it "responds to hook_after" do
|
100
|
+
Foo.should respond_to(:hook_after)
|
55
101
|
end
|
56
102
|
|
57
|
-
|
58
|
-
|
59
|
-
|
103
|
+
describe "hook_after" do
|
104
|
+
let(:foo) { Foo.new }
|
105
|
+
|
106
|
+
it "calls the hook after sending the event" do
|
107
|
+
foo.should_receive(:submit_without_after_hook).ordered
|
108
|
+
foo.should_receive(:submission_postconditions).ordered
|
109
|
+
foo.submit
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when postcondition is met (hook returns true)" do
|
113
|
+
it "returns the original return value of the event" do
|
114
|
+
foo.submit.should == "SUBMITTED"
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when event involves database changes" do
|
118
|
+
it "changes the record" do
|
119
|
+
foo.submit
|
120
|
+
foo.should be_persisted
|
121
|
+
end
|
60
122
|
end
|
61
123
|
end
|
62
124
|
|
63
|
-
|
64
|
-
|
65
|
-
|
125
|
+
context" when postcondition is not met (hook returns false)" do
|
126
|
+
before { foo.ready = false }
|
127
|
+
|
128
|
+
it "returns false" do
|
129
|
+
foo.submit.should be_false
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when event involves database changes" do
|
133
|
+
it "does not change the foo record" do
|
134
|
+
foo.submit
|
135
|
+
foo.should_not be_persisted
|
136
|
+
end
|
137
|
+
end
|
66
138
|
end
|
67
139
|
end
|
68
140
|
end
|
Binary file
|
data/spec/schema.rb
ADDED
data/spec/spec_helper.rb
CHANGED
@@ -3,3 +3,10 @@ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib
|
|
3
3
|
require 'event_hooks'
|
4
4
|
|
5
5
|
require 'rspec'
|
6
|
+
|
7
|
+
def load_schema
|
8
|
+
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
9
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
10
|
+
ActiveRecord::Base.establish_connection(config['sqlite3'])
|
11
|
+
load(File.dirname(__FILE__) + "/schema.rb")
|
12
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_hooks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -27,6 +27,38 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 2.12.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: activerecord
|
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: sqlite3
|
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'
|
30
62
|
description: Add hooks before or after events
|
31
63
|
email:
|
32
64
|
- pablo@pcr-webdesign.com
|
@@ -45,7 +77,10 @@ files:
|
|
45
77
|
- lib/event_hooks/errors.rb
|
46
78
|
- lib/event_hooks/event_hooks.rb
|
47
79
|
- lib/event_hooks/version.rb
|
80
|
+
- spec/database.yml
|
48
81
|
- spec/event_hooks/event_hooks_spec.rb
|
82
|
+
- spec/hook.sqlite3.db
|
83
|
+
- spec/schema.rb
|
49
84
|
- spec/spec_helper.rb
|
50
85
|
homepage: ''
|
51
86
|
licenses: []
|
@@ -72,5 +107,8 @@ signing_key:
|
|
72
107
|
specification_version: 3
|
73
108
|
summary: HookEvents allows you to add pre and post-conditions to events
|
74
109
|
test_files:
|
110
|
+
- spec/database.yml
|
75
111
|
- spec/event_hooks/event_hooks_spec.rb
|
112
|
+
- spec/hook.sqlite3.db
|
113
|
+
- spec/schema.rb
|
76
114
|
- spec/spec_helper.rb
|