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 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