active_model_listener 0.2.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/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