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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77099f72f8abc9a8cdddad94a14066bacf6ed237
4
- data.tar.gz: 7912095ef91683daa7a35a5ae951b06674d57ee7
3
+ metadata.gz: af4258aa0ac4cfba0b3f42a7aab2db6d91daf7a3
4
+ data.tar.gz: b2493f00d932a61c9ea7ecaabad17fa43bb25dc0
5
5
  SHA512:
6
- metadata.gz: 1dc22ba6426f9b2f06ef710e6908bb97eac861c6fd0d6810cf887e21814d1531621fcde8ab6a12ccdd75a2a0152f069100ad5b3d75d977cd221db148197c6e7c
7
- data.tar.gz: d079cacae3eb059499f1f008928dd677be4aefbc873420b647a7db588b47f13d6d24fc506bae64395363b292f9fcde29e1d30a6a16f9dd20463ca11f367ac302
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 under develoment and is not ready for production usage.
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
- ## Installation
10
- Add this line to your application's Gemfile:
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 model, include_initial: true, scope: [:all, [:limit, 5], [:order, :id]]
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
- Contribution directions go here.
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
- # Options
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
- after_destroy :notify_destroy
13
+ before_destroy :notify_destroy
13
14
  end
14
15
 
15
16
  module ClassMethods
16
- # Options setter
17
- def action_cable_notification_options= ( broadcasting, options = nil )
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
- # Options getter
26
- def action_cable_notification_options ( broadcasting )
27
- if broadcasting.present?
28
- self.ActionCableNotificationsOptions[broadcasting.to_sym]
29
- else
30
- self.ActionCableNotificationsOptions
31
- end
32
- end
33
-
34
- def scoped_collection ( scope )
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.action_cable_notification_options( broadcasting )
40
- {
41
- collection: self.model_name.collection,
42
- msg: 'add_collection',
43
- data: self.scoped_collection(options[:scope])
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
- # Checks if record is within scope before broadcasting
51
- if self.class.scoped_collection(options[:scope]).include? self
52
- ActionCable.server.broadcast broadcasting,
53
- collection: self.model_name.collection,
54
- msg: 'create',
55
- id: self.id,
56
- data: self
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
- # Checks if record is within scope before broadcasting
69
- if self.class.scoped_collection(options[:scope]).include? self
70
- ActionCable.server.broadcast broadcasting,
71
- collection: self.model_name.collection,
72
- msg: 'update',
73
- id: self.id,
74
- data: changes
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
- # Checks if record is within scope before broadcasting
82
- if self.class.scoped_collection(options[:scope]).include? self
83
- ActionCable.server.broadcast broadcasting,
84
- collection: self.model_name.collection,
85
- msg: 'destroy',
86
- id: self.id
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
- @options = {
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 !@model.respond_to? :ActionCableNotificationsOptions
27
- @model.send('include', ActionCableNotifications::Callbacks)
24
+ if !model.respond_to? :ActionCableNotificationsOptions
25
+ model.send('include', ActionCableNotifications::Callbacks)
26
+ # Set specified options on model
28
27
  end
29
28
 
30
- # Set specified options on model
31
- @model.send('action_cable_notification_options=', @options[:broadcasting], @options)
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(@options[:broadcasting], options[:callback] || block, @options.slice(:coder))
35
+ stream_from(options[:broadcasting], options[:callback] || block, options.slice(:coder))
35
36
 
36
37
  # Transmit initial state if required
37
- if @options[:include_initial]
38
+ if options[:include_initial]
38
39
  # XXX: Check if data should be transmitted
39
- transmit @model.notify_initial @options[:broadcasting]
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
@@ -1,3 +1,3 @@
1
1
  module ActionCableNotifications
2
- VERSION = '0.1.5'
2
+ VERSION = '0.1.6'
3
3
  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.5
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-08-30 00:00:00.000000000 Z
11
+ date: 2016-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails