active_model_listener 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jeff Dean
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # ActiveModelListener
2
+
3
+ Simple, global ActiveRecord event observers, using a middleware architecture, that can easily be turned on and off. Designed for audit trails, activity feeds and other application-level event handlers.
4
+
5
+ ## Usage
6
+
7
+ First, require Active Model Listener above your rails initializer:
8
+
9
+ # environment.rb
10
+ require 'active_model_listener'
11
+ Rails::Initializer.run do |config|
12
+ # ...
13
+ end
14
+
15
+ Add the listeners to the ActiveModelListener in an initializer:
16
+
17
+ # config/initializers/active_model_listener.rb
18
+ ActiveModelListener.listeners << ActivityFeedListener
19
+
20
+ Then, create a listener class that defines methods for after_create, after_update and after_destroy:
21
+
22
+ class ActivityFeedListener
23
+ class << self
24
+ def after_create(record)
25
+ description = "#{record.class.name} was created"
26
+ publish_activity_feed_items record, description
27
+ end
28
+
29
+ def after_update(record)
30
+ description = "#{record.class.name} was updated"
31
+ publish_activity_feed_items record, description
32
+ end
33
+
34
+ def after_destroy(record)
35
+ description = "#{record.class.name} was deleted"
36
+ publish_activity_feed_items record, description
37
+ end
38
+
39
+ def publish_activity_feed_items(record, description)
40
+ record.activity_feed_item_subscribers.each do |subscriber|
41
+ ActivityFeedItem.create :user => subscriber, :description => description
42
+ end
43
+ end
44
+
45
+ private :publish_activity_feed_items
46
+ end
47
+ end
48
+
49
+ ## Turning off listeners in specs
50
+
51
+ When unit testing if your listeners are all firing your unit tests become integration tests. To avoid this, you can easily turn off listeners for all specs all the time:
52
+
53
+ Spec::Runner.configure do |config|
54
+ config.before(:each) do
55
+ ActiveModelListener.listeners.clear
56
+ end
57
+ end
58
+
59
+ Then, when you want them back on again, you can either turn them back on for a spec:
60
+
61
+ describe "Integrating with listeners" do
62
+ before do
63
+ ActiveModelListener.listeners << FooListener
64
+ end
65
+ end
66
+
67
+ ## Specifying a subset of listeners to use
68
+
69
+ When doing data imports, migrations or certain actions that need to only use certain listeners, you can easily specify which ones you'd like to use:
70
+
71
+ ActiveModelListener.with_listeners AuditListener, ActivityListener do
72
+ Article.create! :title => "foo"
73
+ end
74
+
75
+ After the block runs, the original listeners are restored.
76
+
77
+ If you want to run some code with no listeners, you can do so with:
78
+
79
+ ActiveModelListener.without_listeners do
80
+ Article.create! :title => "foo"
81
+ end
82
+
83
+ ## Um. Don't observers already do this?
84
+
85
+ ActiveRecord Observers are:
86
+
87
+ * Hard to apply to large numbers of models (you have to explicitly declare every one)
88
+ * Hard to turn off in tests
89
+ * Hard to selectively enable / disable
90
+
91
+ ActiveModelListener applies to all ActiveRecord models anywhere in your app, all the time. ActiveModelListener listeners are very easy to turn off during unit tests as well.
92
+
93
+ ## Copyright
94
+
95
+ Copyright (c) 2009 Jeff Dean. See LICENSE for details.
96
+
@@ -0,0 +1,90 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ class GenericListener
4
+ def self.after_create(object)
5
+ end
6
+ def self.after_update(object)
7
+ end
8
+ def self.after_destroy(object)
9
+ end
10
+ end
11
+
12
+ class FooListener < GenericListener
13
+ end
14
+
15
+ class BarListener < GenericListener
16
+ end
17
+
18
+ class BazListener < GenericListener
19
+ end
20
+
21
+ describe ActiveModelListener do
22
+ before do
23
+ build_model :articles do
24
+ string :title
25
+ end
26
+
27
+ ActiveModelListener.listeners.clear
28
+ ActiveModelListener.listeners << FooListener
29
+ ActiveModelListener.listeners << BarListener
30
+ end
31
+
32
+ describe "with_listeners" do
33
+ it "only fires those listeners that are present" do
34
+ FooListener.should_receive(:after_create)
35
+ BarListener.should_not_receive(:after_create)
36
+
37
+ ActiveModelListener.with_listeners([FooListener]) do
38
+ Article.create! :title => "foo"
39
+ end
40
+ end
41
+
42
+ it "splats the args" do
43
+ FooListener.should_receive(:after_create)
44
+ BarListener.should_receive(:after_create)
45
+ BarListener.should_not_receive(:after_create)
46
+
47
+ ActiveModelListener.with_listeners(FooListener, BarListener) do
48
+ Article.create! :title => "foo"
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "without_listeners" do
54
+ it "fires no listeners" do
55
+ FooListener.should_not_receive(:after_create)
56
+ BarListener.should_not_receive(:after_create)
57
+
58
+ ActiveModelListener.without_listeners do
59
+ Article.create! :title => "foo"
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "after create" do
65
+ it "should fire off all wired up events" do
66
+ FooListener.should_receive(:after_create)
67
+ BarListener.should_receive(:after_create)
68
+ Article.create! :title => "foo"
69
+ end
70
+ end
71
+
72
+ describe "after update" do
73
+ it "should fire off all wired up events" do
74
+ article = Article.create
75
+ FooListener.should_receive(:after_update).with(article)
76
+ BarListener.should_receive(:after_update).with(article)
77
+ article.save
78
+ end
79
+ end
80
+
81
+ describe "after destroy" do
82
+ it "should fire off all wired up events" do
83
+ article = Article.create
84
+ FooListener.should_receive(:after_destroy).with(article)
85
+ BarListener.should_receive(:after_destroy).with(article)
86
+ article.destroy
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec'
2
+ require 'acts_as_fu'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'active_model_listener'
7
+
8
+ Spec::Runner.configure do |config|
9
+ config.include ActsAsFu
10
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_model_listener
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Dean
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-03 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: jeff@zilkey.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.md
25
+ files:
26
+ - LICENSE
27
+ - README.md
28
+ has_rdoc: true
29
+ homepage: http://github.com/zilkey/active_model_listener
30
+ licenses: []
31
+
32
+ post_install_message:
33
+ rdoc_options:
34
+ - --charset=UTF-8
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project:
52
+ rubygems_version: 1.3.3
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: Simple, global ActiveRecord event observers, using a middleware architecture, that can easily be turned on and off. Designed for audit trails, activity feeds and other app-level event handlers
56
+ test_files:
57
+ - spec/active_model_listener_spec.rb
58
+ - spec/spec_helper.rb