pubsub_notifier 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.
- checksums.yaml +7 -0
- data/README.md +174 -0
- data/Rakefile +6 -0
- data/lib/generators/pubsub_notifier/install/USAGE +2 -0
- data/lib/generators/pubsub_notifier/install/install_generator.rb +13 -0
- data/lib/generators/pubsub_notifier/install/templates/application_notifier.rb +2 -0
- data/lib/generators/pubsub_notifier/install/templates/initializer.rb +10 -0
- data/lib/generators/rails/USAGE +8 -0
- data/lib/generators/rails/notifier_generator.rb +13 -0
- data/lib/generators/rails/templates/notifier.rb +15 -0
- data/lib/generators/rspec/notifier_generator.rb +9 -0
- data/lib/generators/rspec/templates/notifier_spec.rb +5 -0
- data/lib/generators/test_unit/notifier_generator.rb +9 -0
- data/lib/generators/test_unit/templates/notifier_test.rb +11 -0
- data/lib/pubsub_notifier.rb +35 -0
- data/lib/pubsub_notifier/acts_as_notifier.rb +26 -0
- data/lib/pubsub_notifier/base.rb +43 -0
- data/lib/pubsub_notifier/broadcasters.rb +31 -0
- data/lib/pubsub_notifier/broadcasters/active_job_broadcaster.rb +32 -0
- data/lib/pubsub_notifier/client.rb +43 -0
- data/lib/pubsub_notifier/config.rb +13 -0
- data/lib/pubsub_notifier/proxy.rb +38 -0
- data/lib/pubsub_notifier/pubsub.rb +9 -0
- data/lib/pubsub_notifier/railtie.rb +18 -0
- data/lib/pubsub_notifier/slack_client.rb +86 -0
- data/lib/pubsub_notifier/version.rb +3 -0
- data/spec/pubsub_notifier_spec.rb +32 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/models/member.rb +6 -0
- data/spec/support/models/user.rb +6 -0
- data/spec/support/notifiers/admin_notifier.rb +13 -0
- data/spec/support/notifiers/application_notifier.rb +2 -0
- data/spec/support/notifiers/user_notifier.rb +13 -0
- metadata +125 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 7afc8a84729f47928bca7b4b3b432ceba1d98458
|
|
4
|
+
data.tar.gz: 10c9907f794ebd014e0dbe372b386ca6008f08e6
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4e770a775b9e7f04cb9f59cefb02e845f06dbd2018f199841a35bdb43dd55f11bd2c08c30129a80fe351ac04c7e8c4d754d3e924780999cbd427fc912066b077
|
|
7
|
+
data.tar.gz: '03547309641d77529300b6b9d3116ba7b924beef44fd9457de49ff50234452fa235f4e6e36005cf4aaab11ab498c14a095b37edb019d63903e2a39c9fc809de2'
|
data/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# PubsubNotifier
|
|
2
|
+
|
|
3
|
+
Publish-Subscribe Notifier for Ruby on Rails.
|
|
4
|
+
|
|
5
|
+
This gem relies on [krisleech/wisper](https://github.com/krisleech/wisper/) provides Pub/Sub capabilities.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'pubsub_notifier'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And you can run the generator, which will set up an application notifier with some useful defaults for you:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
rails g pubsub_notifier:install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
After generating your application notifier, restart the Rails server so that Rails can pick up any classes in the new `app/notifiers/` directory.
|
|
20
|
+
|
|
21
|
+
Optionally, you need to perform asynchronously. Add `sidekiq` or `resuque` to your Gemfile:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
gem 'sidekiq'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then set your queue adapter of active_job:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
Rails.application.config.active_job.queue_adapter = :sidekiq
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
### ActiveRecord
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
class User < ApplicationRecord
|
|
39
|
+
subscribe :UserMailer
|
|
40
|
+
subscribe :UserNotifier, async: true, queue: :high
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class UserMailer < ApplicationMailer
|
|
44
|
+
acts_as_notifier
|
|
45
|
+
|
|
46
|
+
default from: 'admin@example.com'
|
|
47
|
+
|
|
48
|
+
def welcome(user)
|
|
49
|
+
@user = user
|
|
50
|
+
mail(to: @user.email, subject: 'Welcome to My Awesome Site')
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class UserNotifier < ApplicationNotifier
|
|
55
|
+
use :slack, channel: '#general', username: 'angel', icon_emoji: ':innocent:'
|
|
56
|
+
|
|
57
|
+
def welcome(user)
|
|
58
|
+
notify_success("#{user.name} has joined.")
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
user = User.first
|
|
63
|
+
user.broadcast(:welcome) # or user.publish(:welcome)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Pure Ruby Object
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
class Register
|
|
70
|
+
include PubsubNotifier::Proxy
|
|
71
|
+
|
|
72
|
+
subscribe :UserRegisterNotifier
|
|
73
|
+
|
|
74
|
+
attr_accessor :name
|
|
75
|
+
|
|
76
|
+
validates :name, presence: true
|
|
77
|
+
|
|
78
|
+
def execute
|
|
79
|
+
if valid?
|
|
80
|
+
broadcast(:success)
|
|
81
|
+
else
|
|
82
|
+
broadcast(:failure)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class UserRegisterNotifier < ApplicationNotifier
|
|
88
|
+
use :slack, channel: '#random', username: 'noreply', icon_emoji: ':grinning:'
|
|
89
|
+
|
|
90
|
+
def success(context)
|
|
91
|
+
notify_success('succeed')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def failure(context)
|
|
95
|
+
notify_failure('failure')
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
register = Register.new(name: 'hello')
|
|
100
|
+
register.execute
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Configuration
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
# config/initializers/pubsub_notifier.rb
|
|
107
|
+
PubsubNotifier.config.logger = Rails.logger
|
|
108
|
+
|
|
109
|
+
require "pubsub_notifier/slack_client"
|
|
110
|
+
|
|
111
|
+
PubsubNotifier::SlackClient.configure do |config|
|
|
112
|
+
config.default_channel = ENV['SLACK_DEFAULT_CHANNEL']
|
|
113
|
+
config.default_username = ENV['SLACK_DEFAULT_USERNAME']
|
|
114
|
+
config.default_icon_emoji = ENV['SLACK_DEFAULT_ICON_EMOJI']
|
|
115
|
+
config.webhook_url = ENV['SLACK_WEBHOOK_URL']
|
|
116
|
+
end
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Generate a Notifier class
|
|
120
|
+
|
|
121
|
+
You can generate a notifier class by generate command:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
rails g notifier user
|
|
125
|
+
create app/notifiers/user_notifier.rb
|
|
126
|
+
invoke test_unit
|
|
127
|
+
create test/notifiers/user_notifier_test.rb
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Implement Notification Client
|
|
131
|
+
|
|
132
|
+
You can easily implement Client for Notification like plugin:
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
module PubsubNotifier
|
|
136
|
+
class SomethingClient < ::PubsubNotifier::Client::Base
|
|
137
|
+
def initialize(options = {})
|
|
138
|
+
# implement this
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def notify_success(message)
|
|
142
|
+
# implement this
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def notify_failure(message)
|
|
146
|
+
# implement this
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def something_special(*args)
|
|
150
|
+
# implement if you need
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
PubsubNotifier.clients :something, PubsubNotifier::SomethingClient
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Then you can use on a notifier class:
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
class SomeNotifier < ApplicationNotifier
|
|
162
|
+
use :something
|
|
163
|
+
|
|
164
|
+
def welcome(recipient)
|
|
165
|
+
notify_success(recipient.name)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
If you want to know more information to implement notification client, please check `lib/pubsub_notifier/slack_client.rb`.
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module PubsubNotifier
|
|
2
|
+
class InstallGenerator < ::Rails::Generators::Base
|
|
3
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
4
|
+
|
|
5
|
+
def create_initializer_file
|
|
6
|
+
template "initializer.rb", "config/initializers/pubsub_notifier.rb"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def create_application_notifier_file
|
|
10
|
+
template "application_notifier.rb", "app/notifiers/application_notifier.rb"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
PubsubNotifier.config.logger = Rails.logger
|
|
2
|
+
|
|
3
|
+
require "pubsub_notifier/slack_client"
|
|
4
|
+
|
|
5
|
+
PubsubNotifier::SlackClient.configure do |config|
|
|
6
|
+
config.default_channel = ENV['SLACK_DEFAULT_CHANNEL']
|
|
7
|
+
config.default_username = ENV['SLACK_DEFAULT_USERNAME']
|
|
8
|
+
config.default_icon_emoji = ENV['SLACK_DEFAULT_ICON_EMOJI']
|
|
9
|
+
config.webhook_url = ENV['SLACK_WEBHOOK_URL']
|
|
10
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Generators
|
|
3
|
+
class NotifierGenerator < ::Rails::Generators::NamedBase
|
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
5
|
+
|
|
6
|
+
def create_notifier_file
|
|
7
|
+
template 'notifier.rb', File.join('app/notifiers', class_path, "#{file_name}_notifier.rb")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
hook_for :test_framework
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<% module_namespacing do -%>
|
|
2
|
+
class <%= class_name %>Notifier < ApplicationNotifier
|
|
3
|
+
use :slack
|
|
4
|
+
|
|
5
|
+
def success(recipient)
|
|
6
|
+
record = recipient
|
|
7
|
+
notify_success("#{record} has successfully created.")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def failure(recipient)
|
|
11
|
+
record = recipient
|
|
12
|
+
notify_failure("#{record} cannot created.")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
<% end -%>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module RSpec
|
|
2
|
+
class NotifierGenerator < ::Rails::Generators::NamedBase
|
|
3
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
4
|
+
|
|
5
|
+
def create_spec_file
|
|
6
|
+
template 'notifier_spec.rb', File.join('spec/notifiers', class_path, "#{file_name}_notifier_spec.rb")
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module TestUnit
|
|
2
|
+
class NotifierGenerator < ::Rails::Generators::NamedBase
|
|
3
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
4
|
+
|
|
5
|
+
def create_spec_file
|
|
6
|
+
template 'notifier_test.rb', File.join('test/notifiers', class_path, "#{file_name}_notifier_test.rb")
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "active_support/core_ext/string/inflections"
|
|
2
|
+
require "wisper"
|
|
3
|
+
|
|
4
|
+
module PubsubNotifier
|
|
5
|
+
def self.configure
|
|
6
|
+
yield config
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.config
|
|
10
|
+
@_config ||= Config.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.register_client(name, klass)
|
|
14
|
+
config.clients[name.to_sym] = klass
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.register_broadcaster(name, klass)
|
|
18
|
+
Wisper.configuration.broadcaster(name.to_sym, klass.new)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.init!
|
|
22
|
+
register_client :logger, PubsubNotifier::Client::LoggerClient
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
require "pubsub_notifier/base"
|
|
27
|
+
require "pubsub_notifier/broadcasters"
|
|
28
|
+
require "pubsub_notifier/client"
|
|
29
|
+
require "pubsub_notifier/config"
|
|
30
|
+
require "pubsub_notifier/proxy"
|
|
31
|
+
require "pubsub_notifier/pubsub"
|
|
32
|
+
require "pubsub_notifier/railtie" if defined?(Rails)
|
|
33
|
+
require "pubsub_notifier/version"
|
|
34
|
+
|
|
35
|
+
PubsubNotifier.init!
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module PubsubNotifier
|
|
2
|
+
module ActsAsNotifier
|
|
3
|
+
def self.included(klass)
|
|
4
|
+
klass.extend ClassMethods
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def acts_as_notifier
|
|
9
|
+
class_eval do
|
|
10
|
+
class << self
|
|
11
|
+
private
|
|
12
|
+
# Override ActionMailer::Base#method_missing
|
|
13
|
+
# https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb#L576
|
|
14
|
+
def method_missing(method_name, *args)
|
|
15
|
+
if action_methods.include?(method_name.to_s)
|
|
16
|
+
::ActionMailer::MessageDelivery.new(self, method_name, *args).tap(&:deliver)
|
|
17
|
+
else
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module PubsubNotifier
|
|
2
|
+
class Base
|
|
3
|
+
class << self
|
|
4
|
+
def use(name, options = {})
|
|
5
|
+
@_client = ( clients[name.to_sym] || clients[:logger] ).new(options)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def client
|
|
9
|
+
@_client ||= clients[:logger].new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def clients
|
|
15
|
+
PubsubNotifier.config.clients
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def method_missing(method_name, *args, &block)
|
|
19
|
+
super unless public_instance_methods.include?(method_name.to_sym)
|
|
20
|
+
new.public_send(method_name, *args, &block)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
24
|
+
public_instance_methods.include?(method_name.to_sym) || super
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def client
|
|
31
|
+
self.class.client
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def method_missing(method_name, *args, &block)
|
|
35
|
+
super unless client.respond_to?(method_name.to_sym)
|
|
36
|
+
client.public_send(method_name, *args, &block)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
40
|
+
client.respond_to?(method_name.to_sym) || super
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module PubsubNotifier
|
|
2
|
+
module Broadcasters
|
|
3
|
+
class Base
|
|
4
|
+
attr_accessor :options
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@options = {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def configure(opts = {})
|
|
11
|
+
self.options = default_options.merge(opts).reject { |_, v| v.nil? }.each_with_object({}) do |(key, proc_or_value), result|
|
|
12
|
+
result[key] = proc_or_value.is_a?(Proc) ? proc_or_value.call : proc_or_value
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def broadcast(subscriber, publisher, event, *args)
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def logger
|
|
23
|
+
PubsubNotifier.config.logger
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def default_options
|
|
27
|
+
{}
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module PubsubNotifier
|
|
2
|
+
module Broadcasters
|
|
3
|
+
class ActiveJobBroadcaster < Base
|
|
4
|
+
def broadcast(subscriber, publisher, event, args)
|
|
5
|
+
configured_job.perform_later(subscriber.name, event, args)
|
|
6
|
+
rescue ActiveJob::SerializationError => e
|
|
7
|
+
# NOTE: Fallback if global_id is blank
|
|
8
|
+
logger.warn { e.inspect }
|
|
9
|
+
configured_job.perform_now(subscriber.name, event, *args)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def configured_job
|
|
15
|
+
BroadcastJob.set(options)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def default_options
|
|
19
|
+
{ wait: nil, wait_until: nil, queue: :default }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class BroadcastJob < ::ActiveJob::Base
|
|
23
|
+
def perform(subscriber_name, event, args)
|
|
24
|
+
subscriber = subscriber_name.constantize
|
|
25
|
+
subscriber.public_send(event, *args)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
PubsubNotifier.register_broadcaster :async, PubsubNotifier::Broadcasters::ActiveJobBroadcaster
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module PubsubNotifier
|
|
2
|
+
module Client
|
|
3
|
+
class Base
|
|
4
|
+
def self.configure
|
|
5
|
+
yield config
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.config
|
|
9
|
+
@_config ||= self::Config.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(options = {}); end
|
|
13
|
+
|
|
14
|
+
def notify_success(message)
|
|
15
|
+
raise NotImplementedError, "#{self.class}##{__method__} is not implemented"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def notify_failure(message)
|
|
19
|
+
raise NotImplementedError, "#{self.class}##{__method__} is not implemented"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def logger
|
|
25
|
+
PubsubNotifier.config.logger
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def config
|
|
29
|
+
self.class.config
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class LoggerClient < Base
|
|
34
|
+
def notify_success(message)
|
|
35
|
+
logger.debug { "[#{self.class}##{__method__}] #{message}" }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def notify_failure(message)
|
|
39
|
+
logger.debug { "[#{self.class}##{__method__}] #{message}" }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module PubsubNotifier
|
|
2
|
+
module Proxy
|
|
3
|
+
def self.included(klass)
|
|
4
|
+
klass.extend ClassMethods
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def subscribe(subscriber_name, options = {})
|
|
9
|
+
subscriber = subscriber_name.to_s.constantize
|
|
10
|
+
broadcaster = ( options.delete(:async) ? broadcasters[:async] : nil ) || broadcasters[:default]
|
|
11
|
+
broadcaster.configure(options) if broadcaster.respond_to?(:configure)
|
|
12
|
+
pubsub.subscribe(subscriber, broadcaster: broadcaster)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def pubsub
|
|
16
|
+
@_pubsub ||= ::PubsubNotifier::Pubsub.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def broadcasters
|
|
22
|
+
Wisper.configuration.broadcasters
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def broadcast(event)
|
|
27
|
+
pubsub.call(event, self)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
alias pubilish broadcast
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def pubsub
|
|
35
|
+
self.class.pubsub
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module PubsubNotifier
|
|
2
|
+
class Railtie < ::Rails::Railtie
|
|
3
|
+
initializer "pubsub_notifier" do
|
|
4
|
+
ActiveSupport.on_load :active_record do
|
|
5
|
+
ActiveRecord::Base.send :include, ::PubsubNotifier::Proxy
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
ActiveSupport.on_load :active_job do
|
|
9
|
+
require "pubsub_notifier/broadcasters/active_job_broadcaster"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
ActiveSupport.on_load :action_mailer do
|
|
13
|
+
require "pubsub_notifier/acts_as_notifier"
|
|
14
|
+
ActionMailer::Base.send :include, PubsubNotifier::ActsAsNotifier
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
module PubsubNotifier
|
|
6
|
+
class SlackClient < ::PubsubNotifier::Client::Base
|
|
7
|
+
attr_reader :channel, :username, :icon_emoji
|
|
8
|
+
|
|
9
|
+
def initialize(options = {})
|
|
10
|
+
@channel = options.delete(:channel) || default_channel
|
|
11
|
+
@username = options.delete(:username) || default_username
|
|
12
|
+
@icon_emoji = options.delete(:icon_emoji) || default_icon_emoji
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def notify_success(message)
|
|
16
|
+
post_slack(
|
|
17
|
+
attachments: [{
|
|
18
|
+
text: message,
|
|
19
|
+
color: 'good',
|
|
20
|
+
mrkdwn_in: ['text'],
|
|
21
|
+
}],
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def notify_failure(message)
|
|
26
|
+
post_slack(
|
|
27
|
+
attachments: [{
|
|
28
|
+
text: message,
|
|
29
|
+
color: 'danger',
|
|
30
|
+
mrkdwn_in: ['text'],
|
|
31
|
+
}],
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def post_slack(payload)
|
|
38
|
+
Net::HTTP.post_form(
|
|
39
|
+
end_point_uri,
|
|
40
|
+
payload: default_payload.merge(payload).to_json,
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def end_point_uri
|
|
45
|
+
@end_point_uri ||= URI.parse(webhook_url)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def default_payload
|
|
49
|
+
{
|
|
50
|
+
channel: channel,
|
|
51
|
+
link_names: 1,
|
|
52
|
+
username: username,
|
|
53
|
+
icon_emoji: icon_emoji,
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def default_channel
|
|
58
|
+
config.default_channel
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def default_username
|
|
62
|
+
config.default_username
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def default_icon_emoji
|
|
66
|
+
config.default_icon_emoji
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def webhook_url
|
|
70
|
+
config.webhook_url
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Config
|
|
74
|
+
attr_accessor :default_channel, :default_username, :default_icon_emoji, :webhook_url
|
|
75
|
+
|
|
76
|
+
def initialize
|
|
77
|
+
@default_channel = ENV['SLACK_DEFAULT_CHANNEL']
|
|
78
|
+
@default_username = ENV['SLACK_DEFAULT_USERNAME']
|
|
79
|
+
@default_icon_emoji = ENV['SLACK_DEFAULT_ICON_EMOJI']
|
|
80
|
+
@webhook_url = ENV['SLACK_WEBHOOK_URL']
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
PubsubNotifier.register_client :slack, PubsubNotifier::SlackClient
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
RSpec.describe PubsubNotifier do
|
|
4
|
+
let(:user) { User.new }
|
|
5
|
+
let(:member) { Member.new }
|
|
6
|
+
|
|
7
|
+
describe "#publish_notifier" do
|
|
8
|
+
it "calls success method on subscribed classes" do
|
|
9
|
+
expect_any_instance_of(AdminNotifier).to receive(:success).once
|
|
10
|
+
expect_any_instance_of(UserNotifier).to receive(:success).once
|
|
11
|
+
user.broadcast(:success)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "calls logger methods on subscribed classes" do
|
|
15
|
+
expect_any_instance_of(Logger).to receive(:debug).exactly(4).times
|
|
16
|
+
member.broadcast(:success)
|
|
17
|
+
member.broadcast(:failure)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "calls only_admin methods on subscribed classes" do
|
|
21
|
+
expect_any_instance_of(AdminNotifier).to receive(:only_admin).once
|
|
22
|
+
expect_any_instance_of(UserNotifier).not_to receive(:only_admin).once
|
|
23
|
+
member.broadcast(:only_admin)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "calls only_user methods on subscribed classes" do
|
|
27
|
+
expect_any_instance_of(UserNotifier).to receive(:only_user).once
|
|
28
|
+
expect_any_instance_of(AdminNotifier).not_to receive(:only_user).once
|
|
29
|
+
member.broadcast(:only_user)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require "bundler/setup"
|
|
2
|
+
require "pubsub_notifier"
|
|
3
|
+
|
|
4
|
+
require "pry"
|
|
5
|
+
|
|
6
|
+
require_relative "support/notifiers/application_notifier"
|
|
7
|
+
require_relative "support/notifiers/admin_notifier"
|
|
8
|
+
require_relative "support/notifiers/user_notifier"
|
|
9
|
+
require_relative "support/models/member"
|
|
10
|
+
require_relative "support/models/user"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class AdminNotifier < ApplicationNotifier
|
|
2
|
+
def success(recipient)
|
|
3
|
+
notify_success("#{recipient.class}##{__method__}")
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def failure(recipient)
|
|
7
|
+
notify_failure("#{recipient.class}##{__method__}")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def only_admin(recipient)
|
|
11
|
+
notify_success("#{recipient.class}##{__method__}")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class UserNotifier < ApplicationNotifier
|
|
2
|
+
def success(recipient)
|
|
3
|
+
notify_success("#{recipient.class}##{__method__}")
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def failure(recipient)
|
|
7
|
+
notify_failure("#{recipient.class}##{__method__}")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def only_user(recipient)
|
|
11
|
+
notify_success("#{recipient.class}##{__method__}")
|
|
12
|
+
end
|
|
13
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: pubsub_notifier
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Yoshiyuki Hirano
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-07-13 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: activesupport
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 3.0.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 3.0.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: wisper
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 2.0.0
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 2.0.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: bundler
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.15'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.15'
|
|
55
|
+
description: Pub/Sub Notifier for Ruby on Rails
|
|
56
|
+
email:
|
|
57
|
+
- yhirano@me.com
|
|
58
|
+
executables: []
|
|
59
|
+
extensions: []
|
|
60
|
+
extra_rdoc_files: []
|
|
61
|
+
files:
|
|
62
|
+
- README.md
|
|
63
|
+
- Rakefile
|
|
64
|
+
- lib/generators/pubsub_notifier/install/USAGE
|
|
65
|
+
- lib/generators/pubsub_notifier/install/install_generator.rb
|
|
66
|
+
- lib/generators/pubsub_notifier/install/templates/application_notifier.rb
|
|
67
|
+
- lib/generators/pubsub_notifier/install/templates/initializer.rb
|
|
68
|
+
- lib/generators/rails/USAGE
|
|
69
|
+
- lib/generators/rails/notifier_generator.rb
|
|
70
|
+
- lib/generators/rails/templates/notifier.rb
|
|
71
|
+
- lib/generators/rspec/notifier_generator.rb
|
|
72
|
+
- lib/generators/rspec/templates/notifier_spec.rb
|
|
73
|
+
- lib/generators/test_unit/notifier_generator.rb
|
|
74
|
+
- lib/generators/test_unit/templates/notifier_test.rb
|
|
75
|
+
- lib/pubsub_notifier.rb
|
|
76
|
+
- lib/pubsub_notifier/acts_as_notifier.rb
|
|
77
|
+
- lib/pubsub_notifier/base.rb
|
|
78
|
+
- lib/pubsub_notifier/broadcasters.rb
|
|
79
|
+
- lib/pubsub_notifier/broadcasters/active_job_broadcaster.rb
|
|
80
|
+
- lib/pubsub_notifier/client.rb
|
|
81
|
+
- lib/pubsub_notifier/config.rb
|
|
82
|
+
- lib/pubsub_notifier/proxy.rb
|
|
83
|
+
- lib/pubsub_notifier/pubsub.rb
|
|
84
|
+
- lib/pubsub_notifier/railtie.rb
|
|
85
|
+
- lib/pubsub_notifier/slack_client.rb
|
|
86
|
+
- lib/pubsub_notifier/version.rb
|
|
87
|
+
- spec/pubsub_notifier_spec.rb
|
|
88
|
+
- spec/spec_helper.rb
|
|
89
|
+
- spec/support/models/member.rb
|
|
90
|
+
- spec/support/models/user.rb
|
|
91
|
+
- spec/support/notifiers/admin_notifier.rb
|
|
92
|
+
- spec/support/notifiers/application_notifier.rb
|
|
93
|
+
- spec/support/notifiers/user_notifier.rb
|
|
94
|
+
homepage: https://github.com/yhirano55/pubsub_notifier
|
|
95
|
+
licenses:
|
|
96
|
+
- MIT
|
|
97
|
+
metadata: {}
|
|
98
|
+
post_install_message:
|
|
99
|
+
rdoc_options: []
|
|
100
|
+
require_paths:
|
|
101
|
+
- lib
|
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
|
+
requirements:
|
|
104
|
+
- - ">="
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: 2.2.0
|
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '0'
|
|
112
|
+
requirements: []
|
|
113
|
+
rubyforge_project:
|
|
114
|
+
rubygems_version: 2.6.10
|
|
115
|
+
signing_key:
|
|
116
|
+
specification_version: 4
|
|
117
|
+
summary: Pub/Sub Notifier for Ruby on Rails
|
|
118
|
+
test_files:
|
|
119
|
+
- spec/pubsub_notifier_spec.rb
|
|
120
|
+
- spec/spec_helper.rb
|
|
121
|
+
- spec/support/models/member.rb
|
|
122
|
+
- spec/support/models/user.rb
|
|
123
|
+
- spec/support/notifiers/admin_notifier.rb
|
|
124
|
+
- spec/support/notifiers/application_notifier.rb
|
|
125
|
+
- spec/support/notifiers/user_notifier.rb
|