wisper-mongoid 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c417fcf4602a8f9144061fac7f8f77eb490f891a
4
+ data.tar.gz: cb72e823ec94e8202e44f548880390218972e8d1
5
+ SHA512:
6
+ metadata.gz: 0aabd5e0cb1d8c859e348b610890d99acc2406b6af069538c993269a4a5fae814deecf73ec64b17adf6346eb8a564ada07f124411a13d0be91a70a7e8dcced05
7
+ data.tar.gz: e6c541b3b749363dd079d57552297d26f878021ba09422bab0187996b3f88846737729d22e57e17c33f0ece28e1f8e337e9f8b9273e71365468d94551a16e986
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec/db.sqlite3
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ bundler_args: --without=metrics
3
+ script: bundle exec rspec spec
4
+ gemfile:
5
+ - gemfiles/mongoid-3.1
6
+ - gemfiles/mongoid-4.0
7
+ rvm:
8
+ - '1.9.3'
9
+ - '2.2.0'
10
+ - jruby
11
+ - rbx-2
@@ -0,0 +1,3 @@
1
+ ## 0.1.0 (24 Mar 2015)
2
+
3
+ * Initial implementation based on krisleech/wisper-activerecord (Adrian Perez / blackxored)
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rubysl', '~> 2.0', :platforms => :rbx
6
+
7
+ gem 'bundler', '~> 1.5'
8
+ gem 'rake'
9
+ gem 'rspec'
10
+ gem 'pry'
11
+
12
+ group :metrics do
13
+ gem 'flay'
14
+ gem 'simplecov'
15
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Kris Leech
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,199 @@
1
+ # Wisper::Mongoid
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/wisper-mongoid.png)](http://badge.fury.io/rb/wisper-mongoid)
4
+ [![Code Climate](https://codeclimate.com/github/blackxored/wisper-mongoid.png)](https://codeclimate.com/github/blackxored/wisper-mongoid)
5
+ [![Build Status](https://travis-ci.org/blackxored/wisper-mongoid.png?branch=master)](https://travis-ci.org/blackxored/wisper-mongoid)
6
+
7
+ Transparently publish model lifecycle events to subscribers.
8
+
9
+ Using Wisper events is a better alternative to Mongoid callbacks and Observers.
10
+
11
+ Listeners are subscribed to models at runtime.
12
+
13
+ ## Installation
14
+
15
+ ```ruby
16
+ gem 'wisper-mongoid'
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Setup a publisher
22
+
23
+ ```ruby
24
+ class Meeting
25
+ include Mongoid::Document
26
+ include Wisper.model
27
+
28
+ # ...
29
+ end
30
+ ```
31
+
32
+ If you wish all models to broadcast events without having to explicitly include
33
+ `Wisper.model` add the following to an initializer:
34
+
35
+ ```ruby
36
+ Wisper::Mongoid.extend_all
37
+ ```
38
+
39
+ ### Subscribing
40
+
41
+ Subscribe a listener to model instances:
42
+
43
+ ```ruby
44
+ meeting = Meeting.new
45
+ meeting.subscribe(Auditor.new)
46
+ ```
47
+
48
+ Subscribe a block to model instances:
49
+
50
+ ```ruby
51
+ meeting.on(:create_meeting_successful) { |meeting| ... }
52
+ ```
53
+
54
+ Subscribe a listener to _all_ instances of a model:
55
+
56
+ ```ruby
57
+ Meeting.subscribe(Auditor.new)
58
+ ```
59
+
60
+ Please refer to the [Wisper README](https://github.com/krisleech/wisper) for full details about subscribing.
61
+
62
+ The events which are automatically broadcast are:
63
+
64
+ * `after_create`
65
+ * `after_destroy`
66
+ * `create_<model_name>_{successful, failed}`
67
+ * `update_<model_name>_{successful, failed}`
68
+ * `destroy_<model_name>_successful`
69
+
70
+ ### Reacting to Events
71
+
72
+ To receive an event the listener must implement a method matching the name of
73
+ the event with a single argument, the instance of the model.
74
+
75
+ ```ruby
76
+ def create_meeting_successful(meeting)
77
+ # ...
78
+ end
79
+ ```
80
+
81
+ ## Example
82
+
83
+ ### Controller
84
+
85
+ ```ruby
86
+ class MeetingsController < ApplicationController
87
+ def new
88
+ @meeting = Meeting.new
89
+ end
90
+
91
+ def create
92
+ @meeting = Meeting.new(params[:meeting])
93
+ @meeting.subscribe(Auditor.instance)
94
+ @meeting.on(:meeting_create_successful) { redirect_to meeting_path }
95
+ @meeting.on(:meeting_create_failed) { render action: :new }
96
+ @meeting.save
97
+ end
98
+
99
+ def edit
100
+ @meeting = Meeting.find(params[:id])
101
+ end
102
+
103
+ def update
104
+ @meeting = Meeting.find(params[:id])
105
+ @meeting.subscribe(Auditor.instance)
106
+ @meeting.on(:meeting_update_successful) { redirect_to meeting_path }
107
+ @meeting.on(:meeting_update_failed) { render :action => :edit }
108
+ @meeting.update_attributes(params[:meeting])
109
+ end
110
+ end
111
+ ```
112
+
113
+ Using `on` to subscribe a block to handle the response is optional,
114
+ you can still use `if @meeting.save` if you prefer.
115
+
116
+ ### Listener
117
+
118
+ **Which simply records an audit in memory**
119
+
120
+ ```ruby
121
+ class Auditor
122
+ include Singleton
123
+
124
+ attr_accessor :audit
125
+
126
+ def initialize
127
+ @audit = []
128
+ end
129
+
130
+ def after_create(subject)
131
+ push_audit_for('create', subject)
132
+ end
133
+
134
+ def after_update(subject)
135
+ push_audit_for('update', subject)
136
+ end
137
+
138
+ def after_destroy(subject)
139
+ push_audit_for('destroy', subject)
140
+ end
141
+
142
+ def self.audit
143
+ instance.audit
144
+ end
145
+
146
+ private
147
+
148
+ def push_audit_for(action, subject)
149
+ audit.push(audit_for(action, subject))
150
+ end
151
+
152
+ def audit_for(action, subject)
153
+ {
154
+ action: action,
155
+ subject_id: subject.id,
156
+ subject_class: subject.class.to_s,
157
+ changes: subject.previous_changes,
158
+ created_at: Time.now
159
+ }
160
+ end
161
+ end
162
+ ```
163
+
164
+ **Do some CRUD**
165
+
166
+ ```ruby
167
+ Meeting.create(:description => 'Team Retrospective', :starts_at => Time.now + 2.days)
168
+
169
+ meeting = Meeting.find(1)
170
+ meeting.starts_at = Time.now + 2.months
171
+ meeting.save
172
+ ```
173
+
174
+ **And check the audit**
175
+
176
+ ```ruby
177
+ Auditor.audit # => [...]
178
+ ```
179
+
180
+ ## Compatibility
181
+
182
+ Tested on 1.9.3, 2.x, Rubinius and JRuby for Mongoid ~> 3.1, ~> 4.0
183
+
184
+ See the CI [build status](https://travis-ci.org/blackxored/wisper-mongoid) for more information.
185
+
186
+ ## Special Thanks
187
+
188
+ Special thanks to krisleech for creating `wisper` and `wisper-activerecord`,
189
+ this implementation is heavily based on the later.
190
+
191
+ ## Contributing
192
+
193
+ Please submit a Pull Request with specs.
194
+
195
+ ### Running the specs
196
+
197
+ ```
198
+ bundle exec rspec
199
+ ```
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rubysl', '~> 2.0', :platforms => :rbx
4
+
5
+ gem 'rspec'
6
+
7
+ gem 'mongoid', '~> 3.1'
8
+
9
+ gemspec :path => '../'
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rubysl', '~> 2.0', :platforms => :rbx
4
+
5
+ gem 'rspec'
6
+
7
+ gem 'mongoid', '~> 4.0'
8
+
9
+ gemspec :path => '../'
@@ -0,0 +1 @@
1
+ require "wisper/active_record"
@@ -0,0 +1,15 @@
1
+ require "wisper/mongoid/version"
2
+ require "wisper/mongoid/publisher"
3
+
4
+ module Wisper
5
+ def self.model
6
+ ::Wisper::Mongoid::Publisher
7
+ end
8
+
9
+ module Mongoid
10
+ def self.extend_all
11
+ # TODO: Include model on all mongoid documents
12
+ raise NotImplementedError
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ module Wisper
2
+ module Mongoid
3
+ module Publisher
4
+ extend ActiveSupport::Concern
5
+ included do
6
+
7
+ include Wisper::Publisher
8
+
9
+ after_validation :after_validation_broadcast
10
+ after_create :after_create_broadcast, on: :create
11
+ after_update :after_update_broadcast, on: :update
12
+ after_destroy :after_destroy_broadcast, on: :destroy
13
+ end
14
+
15
+ def commit(_attributes = nil)
16
+ warn "[DEPRECATED] use save, create, update_attributes as usual"
17
+ assign_attributes(_attributes) if _attributes.present?
18
+ save
19
+ end
20
+
21
+ module ClassMethods
22
+ def commit(_attributes = nil)
23
+ warn "[DEPRECATED] use save, create, update_attributes as usual"
24
+ new(_attributes).save
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def after_validation_broadcast
31
+ action = new_record? ? 'create' : 'update'
32
+ broadcast("#{action}_#{broadcast_model_name_key}_failed", self) unless errors.empty?
33
+ end
34
+
35
+ def after_create_broadcast
36
+ broadcast(:after_create, self)
37
+ broadcast("create_#{broadcast_model_name_key}_successful", self)
38
+ end
39
+
40
+ def after_update_broadcast
41
+ broadcast(:after_update, self)
42
+ broadcast("update_#{broadcast_model_name_key}_successful", self)
43
+ end
44
+
45
+ def after_destroy_broadcast
46
+ broadcast(:after_destroy, self)
47
+ broadcast("destroy_#{broadcast_model_name_key}_successful", self)
48
+ end
49
+
50
+ def broadcast_model_name_key
51
+ self.class.model_name.param_key
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ module Wisper
2
+ module Mongoid
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,43 @@
1
+ begin
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter 'spec'
5
+ end
6
+ rescue LoadError
7
+ end
8
+
9
+ require 'pry'
10
+ require 'wisper'
11
+ require 'mongoid'
12
+
13
+ puts "Using Mongoid #{Mongoid::VERSION}"
14
+
15
+ Mongoid.load!("spec/support/mongoid.yml", :test)
16
+
17
+ require 'wisper/mongoid'
18
+ require 'support/models'
19
+
20
+ RSpec.configure do |config|
21
+ config.filter_run :focus
22
+ config.run_all_when_everything_filtered = true
23
+
24
+ if config.files_to_run.one?
25
+ config.full_backtrace = true
26
+ config.default_formatter = 'doc'
27
+ end
28
+
29
+ config.profile_examples = 10
30
+
31
+ config.order = :random
32
+
33
+ Kernel.srand config.seed
34
+
35
+ config.expect_with :rspec do |expectations|
36
+ expectations.syntax = :expect
37
+ end
38
+
39
+ config.mock_with :rspec do |mocks|
40
+ mocks.syntax = :expect
41
+ mocks.verify_partial_doubles = true
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ class Meeting
2
+ include Mongoid::Document
3
+ include Mongoid::Timestamps
4
+ include Wisper.model
5
+
6
+ field :title, default: "My Meeting"
7
+ field :location
8
+
9
+ validates :title, presence: true
10
+ end
@@ -0,0 +1,6 @@
1
+ test:
2
+ sessions:
3
+ default:
4
+ database: wisper_test
5
+ hosts:
6
+ - localhost:27017
@@ -0,0 +1,86 @@
1
+ describe 'Mongoid' do
2
+ let(:listener) { double('Listener') }
3
+ let(:model_class) { Meeting }
4
+
5
+ before { Wisper::GlobalListeners.clear }
6
+
7
+ it '.model returns Mongoid module' do
8
+ expect(Wisper.model).to eq(Wisper::Mongoid::Publisher)
9
+ end
10
+
11
+ describe 'when creating' do
12
+ context 'and model is valid' do
13
+ it 'publishes create_<model_name>_successful event to listener' do
14
+ expect(listener).to receive(:create_meeting_successful).with(instance_of(model_class))
15
+ model_class.subscribe(listener)
16
+ model_class.create
17
+ end
18
+ end
19
+
20
+ context 'and model is not valid' do
21
+ it 'publishes create_<model_name>_failed event to listener' do
22
+ expect(listener).to receive(:create_meeting_failed).with(instance_of(model_class))
23
+ model_class.subscribe(listener)
24
+ model_class.create(title: nil)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe 'when updating' do
30
+ before do
31
+ model_class.create!
32
+ end
33
+
34
+ let(:model) { model_class.first }
35
+
36
+ context 'and model is valid' do
37
+ it 'publishes update_<model_name>_successful event to listener' do
38
+ expect(listener).to receive(:update_meeting_successful).with(instance_of(model_class))
39
+ model_class.subscribe(listener)
40
+ model.title = 'foo'
41
+ model.save
42
+ end
43
+ end
44
+
45
+ context 'and model is not valid' do
46
+ it 'publishes update_<model_name>_failed event to listener' do
47
+ expect(listener).to receive(:update_meeting_failed).with(instance_of(model_class))
48
+ model_class.subscribe(listener)
49
+ model.title = nil
50
+ model.save
51
+ end
52
+ end
53
+ end
54
+
55
+ describe 'create' do
56
+ it 'publishes an after_create event to listener' do
57
+ expect(listener).to receive(:after_create).with(instance_of(model_class))
58
+ model_class.subscribe(listener)
59
+ model_class.create
60
+ end
61
+ end
62
+
63
+ describe 'update' do
64
+ before { model_class.create! }
65
+
66
+ let(:model) { model_class.first }
67
+
68
+ it 'publishes an after_update event to listener' do
69
+ expect(listener).to receive(:after_update).with(instance_of(model_class))
70
+ model.subscribe(listener)
71
+ model.update_attributes(title: 'new title')
72
+ end
73
+ end
74
+
75
+ describe 'destroy' do
76
+ before { model_class.create! }
77
+
78
+ let(:model) { model_class.first }
79
+
80
+ it 'publishes an after_destroy event to listener' do
81
+ expect(listener).to receive(:after_destroy).with(instance_of(model_class))
82
+ model_class.subscribe(listener)
83
+ model.destroy
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,12 @@
1
+ describe Wisper::Mongoid::Publisher do
2
+
3
+ it 'includes Wisper::Publisher' do
4
+ klass = Class.new do
5
+ include Mongoid::Document
6
+ include Mongoid::Timestamps
7
+ include Wisper::Mongoid::Publisher
8
+ end
9
+
10
+ expect(klass.ancestors).to include Wisper::Publisher
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'wisper/mongoid/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "wisper-mongoid"
8
+ spec.version = Wisper::Mongoid::VERSION
9
+ spec.authors = ["Adrian Perez"]
10
+ spec.email = ["adrianperez.deb@gmail.com"]
11
+ spec.summary = %q{Subscribe to changes on Mongoid models}
12
+ spec.description = %q{Subscribe to changes on Mongoid models}
13
+ spec.homepage = "https://github.com/blackxored/wisper-mongoid"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+ spec.required_ruby_version = ">= 1.9.3"
21
+
22
+ spec.add_dependency "wisper", "~> 1.3"
23
+ spec.add_dependency "mongoid", ">= 3.1", "< 5"
24
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wisper-mongoid
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Adrian Perez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: wisper
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mongoid
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '5'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '3.1'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '5'
47
+ description: Subscribe to changes on Mongoid models
48
+ email:
49
+ - adrianperez.deb@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - ".gitignore"
55
+ - ".rspec"
56
+ - ".travis.yml"
57
+ - CHANGELOG.md
58
+ - Gemfile
59
+ - LICENSE.txt
60
+ - README.md
61
+ - Rakefile
62
+ - gemfiles/mongoid-3.1
63
+ - gemfiles/mongoid-4.0
64
+ - lib/wisper/activerecord.rb
65
+ - lib/wisper/mongoid.rb
66
+ - lib/wisper/mongoid/publisher.rb
67
+ - lib/wisper/mongoid/version.rb
68
+ - spec/spec_helper.rb
69
+ - spec/support/models.rb
70
+ - spec/support/mongoid.yml
71
+ - spec/wisper/mongoid_spec.rb
72
+ - spec/wisper/publisher_spec.rb
73
+ - wisper-mongoid.gemspec
74
+ homepage: https://github.com/blackxored/wisper-mongoid
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 1.9.3
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.4.5
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Subscribe to changes on Mongoid models
98
+ test_files:
99
+ - spec/spec_helper.rb
100
+ - spec/support/models.rb
101
+ - spec/support/mongoid.yml
102
+ - spec/wisper/mongoid_spec.rb
103
+ - spec/wisper/publisher_spec.rb
104
+ has_rdoc: