action_cable_notifications 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +81 -24
- data/lib/action_cable_notifications/callbacks.rb +88 -41
- data/lib/action_cable_notifications/streams.rb +11 -13
- data/lib/action_cable_notifications/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af4258aa0ac4cfba0b3f42a7aab2db6d91daf7a3
|
4
|
+
data.tar.gz: b2493f00d932a61c9ea7ecaabad17fa43bb25dc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb152248983ea3678b5b2933046a8604cd23ff16de46191709117fafa687a24272cc2bb7f5f6ab3e737ef22f9cd96553e1f21a34ea64c484a0f74a0e41e33029
|
7
|
+
data.tar.gz: 6f19980552466b17e0ab2cdf6424cf86e620e6afdff01c71bb71a9fd6d815acd4d7108580dc59fff69d540620baa38f36561dd0743cf9e136865e715ea53fe99
|
data/README.md
CHANGED
@@ -1,30 +1,12 @@
|
|
1
1
|
# ActionCableNotifications
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/action_cable_notifications.svg)](https://badge.fury.io/rb/action_cable_notifications)
|
3
3
|
|
4
|
-
This gem is
|
4
|
+
**This gem is being developed as part of an internal proyect. It's constantly changing and is not ready for production usage. Use at your own risk!!**
|
5
5
|
|
6
6
|
## Usage
|
7
|
-
How to use my plugin.
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
```ruby
|
13
|
-
gem 'action_cable_notifications'
|
14
|
-
```
|
15
|
-
|
16
|
-
And then execute:
|
17
|
-
```bash
|
18
|
-
$ bundle
|
19
|
-
```
|
20
|
-
|
21
|
-
Or install it yourself as:
|
22
|
-
```bash
|
23
|
-
$ gem install action_cable_notifications
|
24
|
-
```
|
25
|
-
|
26
|
-
## Usage
|
27
|
-
Create a new channel (`rails g cahnnel Test`) or modify existing one including `ActionCableNotifications::Streams` module.
|
8
|
+
### Server side
|
9
|
+
On **server-side**, create a new channel (`rails g cahnnel Test`) or modify existing one including `ActionCableNotifications::Streams` module.
|
28
10
|
|
29
11
|
```ruby
|
30
12
|
class TestChannel < ApplicationCable::Channel
|
@@ -32,7 +14,7 @@ class TestChannel < ApplicationCable::Channel
|
|
32
14
|
include ActionCableNotifications::Streams
|
33
15
|
|
34
16
|
def subscribed
|
35
|
-
stream_notifications_for
|
17
|
+
stream_notifications_for Users, include_initial: true, scope: [:all, [:limit, 5], [:order, :id]]
|
36
18
|
end
|
37
19
|
|
38
20
|
def unsubscribed
|
@@ -41,7 +23,7 @@ class TestChannel < ApplicationCable::Channel
|
|
41
23
|
end
|
42
24
|
```
|
43
25
|
|
44
|
-
Method stream_notifications_for receives the following parameters:
|
26
|
+
Method `stream_notifications_for` receives the following parameters:
|
45
27
|
|
46
28
|
```ruby
|
47
29
|
stream_notifications_for(model, options = {}, &block)
|
@@ -63,8 +45,83 @@ stream_notifications_for(model, options = {}, &block)
|
|
63
45
|
```
|
64
46
|
* block: **(Proc)** - Same as options[:callback]
|
65
47
|
|
48
|
+
### Client side
|
49
|
+
On **client-side**, use action_cable subscriptions as stated in the documentation. Received data will have the following format:
|
50
|
+
|
51
|
+
#### Initial values for collection
|
52
|
+
```javascript
|
53
|
+
{
|
54
|
+
collection: 'users',
|
55
|
+
msg: 'add_collection',
|
56
|
+
data: [
|
57
|
+
{
|
58
|
+
id: 1,
|
59
|
+
username: 'username 1',
|
60
|
+
color: 'red'
|
61
|
+
},
|
62
|
+
{
|
63
|
+
id: 2,
|
64
|
+
username: 'username 2',
|
65
|
+
color: 'green'
|
66
|
+
]
|
67
|
+
}
|
68
|
+
```
|
69
|
+
|
70
|
+
#### Create event
|
71
|
+
```javascript
|
72
|
+
{
|
73
|
+
collection: 'users',
|
74
|
+
msg: 'create',
|
75
|
+
id: 3,
|
76
|
+
data: {
|
77
|
+
id: 3,
|
78
|
+
username: 'username 3'
|
79
|
+
color: 'blue'
|
80
|
+
}
|
81
|
+
}
|
82
|
+
```
|
83
|
+
|
84
|
+
#### Update event
|
85
|
+
Update event will only transmit changed fields for the model.
|
86
|
+
```javascript
|
87
|
+
{
|
88
|
+
collection: 'users',
|
89
|
+
msg: 'update',
|
90
|
+
id: 2,
|
91
|
+
data: {
|
92
|
+
color: 'light blue'
|
93
|
+
}
|
94
|
+
}
|
95
|
+
```
|
96
|
+
|
97
|
+
#### Destroy event
|
98
|
+
```javascript
|
99
|
+
{
|
100
|
+
collection: 'users',
|
101
|
+
msg: 'destroy',
|
102
|
+
id: 2
|
103
|
+
}
|
104
|
+
```
|
105
|
+
|
106
|
+
## Installation
|
107
|
+
Add this line to your application's Gemfile:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
gem 'action_cable_notifications'
|
111
|
+
```
|
112
|
+
|
113
|
+
And then execute:
|
114
|
+
```bash
|
115
|
+
$ bundle
|
116
|
+
```
|
117
|
+
|
118
|
+
Or install it yourself as:
|
119
|
+
```bash
|
120
|
+
$ gem install action_cable_notifications
|
121
|
+
```
|
122
|
+
|
66
123
|
## Contributing
|
67
|
-
|
124
|
+
Contributions are welcome. We will be happy to receive issues, comments and pull-request to make this gem better.
|
68
125
|
|
69
126
|
## License
|
70
127
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -3,61 +3,95 @@ module ActionCableNotifications
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
#
|
6
|
+
# Action cable notification options storage
|
7
7
|
class_attribute :ActionCableNotificationsOptions
|
8
8
|
self.ActionCableNotificationsOptions = {}
|
9
9
|
|
10
|
+
# Register Callbacks
|
10
11
|
after_update :notify_update
|
11
12
|
after_create :notify_create
|
12
|
-
|
13
|
+
before_destroy :notify_destroy
|
13
14
|
end
|
14
15
|
|
15
16
|
module ClassMethods
|
16
|
-
|
17
|
-
|
17
|
+
|
18
|
+
#
|
19
|
+
# Sets or removes notificacions options for Active Record model
|
20
|
+
#
|
21
|
+
# @param [sym] broadcasting Topic name to broadcast in
|
22
|
+
# @param [hash] options Hash containing notification options
|
23
|
+
#
|
24
|
+
def broadcast_notifications_from ( broadcasting, options = nil )
|
18
25
|
if options.present?
|
26
|
+
# Default options
|
27
|
+
options = {
|
28
|
+
actions: [:create, :update, :destroy],
|
29
|
+
scope: :all # Default collection scope
|
30
|
+
}.merge(options)
|
31
|
+
|
19
32
|
self.ActionCableNotificationsOptions[broadcasting.to_sym] = options
|
20
33
|
else
|
21
34
|
self.ActionCableNotificationsOptions.except! broadcasting.to_sym
|
22
35
|
end
|
23
36
|
end
|
24
37
|
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
Array(Array(scope).inject(self) {|o, a| o.try(*a)})
|
38
|
+
#
|
39
|
+
# Returns collection scoped as specified in parameters.
|
40
|
+
#
|
41
|
+
# @param [Array] scope Contains the scopes to be applied. For
|
42
|
+
# example: [[:limit, 5], [:order, :id]]
|
43
|
+
#
|
44
|
+
# @return [ActiveRecordRelation] Results fetched from the database
|
45
|
+
#
|
46
|
+
def scoped_collection ( scope=:all )
|
47
|
+
Array(scope).inject(self) {|o, a| o.try(*a)}
|
36
48
|
end
|
37
49
|
|
50
|
+
#
|
51
|
+
# Retrieves initial values to be sent to clients upon subscription
|
52
|
+
#
|
53
|
+
# @param [Sym] broadcasting Name of broadcasting stream
|
54
|
+
#
|
55
|
+
# @return [Hash] Hash containing the results in the following format:
|
56
|
+
# {
|
57
|
+
# collection: self.model_name.collection,
|
58
|
+
# msg: 'add_collection',
|
59
|
+
# data: self.scoped_collection(options[:scope])
|
60
|
+
# }
|
38
61
|
def notify_initial ( broadcasting )
|
39
|
-
options = self.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
62
|
+
options = self.ActionCableNotificationsOptions[broadcasting.to_sym]
|
63
|
+
if options.present?
|
64
|
+
{
|
65
|
+
collection: self.model_name.collection,
|
66
|
+
msg: 'add_collection',
|
67
|
+
data: self.scoped_collection(options[:scope])
|
68
|
+
}
|
69
|
+
end
|
45
70
|
end
|
46
71
|
end
|
47
72
|
|
73
|
+
#
|
74
|
+
# Broadcast notifications when a new record is created
|
75
|
+
#
|
48
76
|
def notify_create
|
49
77
|
self.ActionCableNotificationsOptions.each do |broadcasting, options|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
78
|
+
if options[:actions].include? :create
|
79
|
+
# Checks if record is within scope before broadcasting
|
80
|
+
if self.class.scoped_collection(options[:scope]).where(id: self.id)
|
81
|
+
ActionCable.server.broadcast broadcasting,
|
82
|
+
collection: self.model_name.collection,
|
83
|
+
msg: 'added',
|
84
|
+
id: self.id,
|
85
|
+
data: self
|
86
|
+
end
|
57
87
|
end
|
58
88
|
end
|
59
89
|
end
|
60
90
|
|
91
|
+
#
|
92
|
+
# Broadcast notifications when a record is updated. Only changed
|
93
|
+
# field will be sent.
|
94
|
+
#
|
61
95
|
def notify_update
|
62
96
|
changes = {}
|
63
97
|
self.changes.each do |k,v|
|
@@ -65,25 +99,38 @@ module ActionCableNotifications
|
|
65
99
|
end
|
66
100
|
|
67
101
|
self.ActionCableNotificationsOptions.each do |broadcasting, options|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
102
|
+
if options[:actions].include? :update
|
103
|
+
# Checks if record is within scope before broadcasting
|
104
|
+
if self.class.scoped_collection(options[:scope]).where(id: self.id)
|
105
|
+
# XXX: Performance required. For small data sets this should be
|
106
|
+
# fast enough, but for large data sets this could be slow. As
|
107
|
+
# clients should have a limited subset of the dataset loaded at a
|
108
|
+
# time, caching the results already sent to clients in server memory
|
109
|
+
# should not have a big impact in memory usage but can improve
|
110
|
+
# performance for large data sets where only a sub
|
111
|
+
ActionCable.server.broadcast broadcasting,
|
112
|
+
collection: self.model_name.collection,
|
113
|
+
msg: 'changed',
|
114
|
+
id: self.id,
|
115
|
+
data: changes
|
116
|
+
end
|
75
117
|
end
|
76
118
|
end
|
77
119
|
end
|
78
120
|
|
121
|
+
#
|
122
|
+
# Broadcast notifications when a record is destroyed.
|
123
|
+
#
|
79
124
|
def notify_destroy
|
80
125
|
self.ActionCableNotificationsOptions.each do |broadcasting, options|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
126
|
+
if options[:actions].include? :destroy
|
127
|
+
# Checks if record is within scope before broadcasting
|
128
|
+
if self.class.scoped_collection(options[:scope]).where(id: self.id)
|
129
|
+
ActionCable.server.broadcast broadcasting,
|
130
|
+
collection: self.model_name.collection,
|
131
|
+
msg: 'removed',
|
132
|
+
id: self.id
|
133
|
+
end
|
87
134
|
end
|
88
135
|
end
|
89
136
|
end
|
@@ -9,10 +9,8 @@ module ActionCableNotifications
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def stream_notifications_for(model, options = {}, &block)
|
12
|
-
@model = model
|
13
|
-
|
14
12
|
# Default options
|
15
|
-
|
13
|
+
options = {
|
16
14
|
actions: [:create, :update, :destroy],
|
17
15
|
broadcasting: model.model_name.collection,
|
18
16
|
callback: nil,
|
@@ -23,29 +21,29 @@ module ActionCableNotifications
|
|
23
21
|
}.merge(options)
|
24
22
|
|
25
23
|
# Checks if model already includes notification callbacks
|
26
|
-
if
|
27
|
-
|
24
|
+
if !model.respond_to? :ActionCableNotificationsOptions
|
25
|
+
model.send('include', ActionCableNotifications::Callbacks)
|
26
|
+
# Set specified options on model
|
28
27
|
end
|
29
28
|
|
30
|
-
#
|
31
|
-
|
29
|
+
# Sets broadcast options if they are not already present in the model
|
30
|
+
if not model.ActionCableNotificationsOptions.key? options[:broadcasting]
|
31
|
+
model.broadcast_notifications_from options[:broadcasting], options
|
32
|
+
end
|
32
33
|
|
33
34
|
# Start streaming
|
34
|
-
stream_from(
|
35
|
+
stream_from(options[:broadcasting], options[:callback] || block, options.slice(:coder))
|
35
36
|
|
36
37
|
# Transmit initial state if required
|
37
|
-
if
|
38
|
+
if options[:include_initial]
|
38
39
|
# XXX: Check if data should be transmitted
|
39
|
-
transmit
|
40
|
+
transmit model.notify_initial options[:broadcasting]
|
40
41
|
end
|
41
42
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def unsubscribed
|
45
46
|
stop_all_streams
|
46
|
-
|
47
|
-
# Unset options for this channel on model
|
48
|
-
@model.send('action_cable_notification_options=', @options[:broadcasting], nil)
|
49
47
|
end
|
50
48
|
|
51
49
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: action_cable_notifications
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ByS Sistemas de Control
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|