event_hooks 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,8 +1,13 @@
1
1
  # EventHooks
2
2
 
3
- EventHooks enhances Ruby classes to allow adding pre-conditions to method calls (events).
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
@@ -1,3 +1,3 @@
1
1
  module EventHooks
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: spec/hook.sqlite3.db
@@ -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 Sub; end
27
+ class Bar; end
25
28
 
26
29
  it "responds to hook_before" do
27
- Sub.should respond_to(:hook_before)
30
+ Bar.should respond_to(:hook_before)
28
31
  end
29
- end
30
32
 
31
- describe 'hook_before' do
32
- let(:sm) { StateMachine.new }
33
+ describe 'hook_before' do
34
+ let(:sm) { StateMachine.new }
33
35
 
34
- it "calls the hook before sending the event" do
35
- sm.should_receive(:submission_preconditions)
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
- sm.submitted.should be_true
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
- context "when precondition is not met (hook returns false)" do
48
- let(:sm) { StateMachine.new(false) }
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
- it "stops the event from happening" do
51
- sm.should_receive(:submit_without_before_hook).never
52
- sm.submit
53
- sm.submitted.should be_false
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
- context "when you try to add another before hook" do
58
- class StateMachine
59
- def another_hook
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
- it "raises a DoubleHook exception" do
64
- expect { StateMachine.send :hook_before, :submit, :another_hook }.
65
- to raise_exception(EventHooks::DoubleHook)
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
@@ -0,0 +1,5 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :foos, :force => true do |t|
3
+ t.string :name
4
+ end
5
+ end
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.2
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-01 00:00:00.000000000 Z
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