action_cable_notifications 0.1.28 → 0.1.30
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 +4 -4
 - data/README.md +17 -5
 - data/app/assets/javascripts/action_cable_notifications/collection.coffee +22 -6
 - data/app/assets/javascripts/action_cable_notifications/default_callbacks.coffee +4 -4
 - data/app/assets/javascripts/action_cable_notifications/store.coffee +4 -5
 - data/lib/action_cable_notifications/channel.rb +55 -42
 - data/lib/action_cable_notifications/channel_actions.rb +3 -2
 - data/lib/action_cable_notifications/channel_cache.rb +44 -0
 - data/lib/action_cable_notifications/hash_db.rb +111 -0
 - data/lib/action_cable_notifications/model.rb +38 -35
 - data/lib/action_cable_notifications/version.rb +1 -1
 - metadata +5 -10
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 64f6e0167fd97bc6b64dc43e1292c331cf7baff7
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: bf24e8703a9953a7be75a3d80f73deb27a118508
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 624a3425d47cd3ea0291abdc706a7b3bc5c12c5d19715775012c364b70d4b00d30907399b3c161357012bca7b33ca4f9afd48ab6f09b4fd95f21c048444b8d1b
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 2848f179da19c2af48b313e07ae81638e481beac62cef85734d9c888e86c10622ffda3230bc2aa091f3589a9434624eebffd805a8d76a9fec6cbc5bfc7c7cb03
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -19,9 +19,17 @@ class TestChannel < ApplicationCable::Channel 
     | 
|
| 
       19 
19 
     | 
    
         
             
              include ActionCableNotifications::Channel
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
              def subscribed
         
     | 
| 
      
 22 
     | 
    
         
            +
                # Config streaming for Customer model with default options
         
     | 
| 
       22 
23 
     | 
    
         
             
                stream_notifications_for Customer
         
     | 
| 
       23 
24 
     | 
    
         
             
                # Can have more than one ActiveRecord model streaming per channel
         
     | 
| 
       24 
     | 
    
         
            -
                stream_notifications_for Invoice, 
     | 
| 
      
 25 
     | 
    
         
            +
                stream_notifications_for Invoice,
         
     | 
| 
      
 26 
     | 
    
         
            +
                  model_options: {
         
     | 
| 
      
 27 
     | 
    
         
            +
                    scope: { 
         
     | 
| 
      
 28 
     | 
    
         
            +
                      limit: 5, 
         
     | 
| 
      
 29 
     | 
    
         
            +
                      order: :id, 
         
     | 
| 
      
 30 
     | 
    
         
            +
                      select: [:id, :customer_id, :seller_id, :amount]
         
     | 
| 
      
 31 
     | 
    
         
            +
                  }
         
     | 
| 
      
 32 
     | 
    
         
            +
                }
         
     | 
| 
       25 
33 
     | 
    
         
             
              end
         
     | 
| 
       26 
34 
     | 
    
         | 
| 
       27 
35 
     | 
    
         
             
              def unsubscribed
         
     | 
| 
         @@ -40,10 +48,14 @@ stream_notifications_for(model, options = {}, &block) 
     | 
|
| 
       40 
48 
     | 
    
         
             
            * options: **(Hash)** - Options to be used for configuracion. Default options are:
         
     | 
| 
       41 
49 
     | 
    
         
             
            ```ruby
         
     | 
| 
       42 
50 
     | 
    
         
             
            {
         
     | 
| 
       43 
     | 
    
         
            -
               
     | 
| 
       44 
     | 
    
         
            -
               
     | 
| 
       45 
     | 
    
         
            -
               
     | 
| 
       46 
     | 
    
         
            -
               
     | 
| 
      
 51 
     | 
    
         
            +
              publication: model.model_name.collection, # Name of the pubsub stream
         
     | 
| 
      
 52 
     | 
    
         
            +
              params: params,                            # Params sent when client subscribes
         
     | 
| 
      
 53 
     | 
    
         
            +
              cache: false,                              # Turn off server-side cache of client-side data
         
     | 
| 
      
 54 
     | 
    
         
            +
              model_options: {
         
     | 
| 
      
 55 
     | 
    
         
            +
                actions: [:create, :update, :destroy],     # Model callbacks to attach to
         
     | 
| 
      
 56 
     | 
    
         
            +
                scope: :all                                # Default collection scope. Can be an ,Array or Hash
         
     | 
| 
      
 57 
     | 
    
         
            +
                track_scope_changes: true                 # During model updates, checks if the changes affect scope inclusion of the resulting record
         
     | 
| 
      
 58 
     | 
    
         
            +
              }
         
     | 
| 
       47 
59 
     | 
    
         
             
            }
         
     | 
| 
       48 
60 
     | 
    
         
             
            ```
         
     | 
| 
       49 
61 
     | 
    
         | 
| 
         @@ -4,7 +4,7 @@ class CableNotifications.Collection 
     | 
|
| 
       4 
4 
     | 
    
         
             
              upstream = (command, params={}) ->
         
     | 
| 
       5 
5 
     | 
    
         
             
                if @sync
         
     | 
| 
       6 
6 
     | 
    
         
             
                  cmd =
         
     | 
| 
       7 
     | 
    
         
            -
                     
     | 
| 
      
 7 
     | 
    
         
            +
                    publication: @publication
         
     | 
| 
       8 
8 
     | 
    
         
             
                    command: command
         
     | 
| 
       9 
9 
     | 
    
         
             
                    params: params
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
         @@ -38,7 +38,7 @@ class CableNotifications.Collection 
     | 
|
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
              # Public methods
         
     | 
| 
       40 
40 
     | 
    
         
             
              #######################################
         
     | 
| 
       41 
     | 
    
         
            -
              constructor: (@store, @name, @ 
     | 
| 
      
 41 
     | 
    
         
            +
              constructor: (@store, @name, @publication=name, callbacks) ->
         
     | 
| 
       42 
42 
     | 
    
         
             
                # Data storage array
         
     | 
| 
       43 
43 
     | 
    
         
             
                @data = []
         
     | 
| 
       44 
44 
     | 
    
         
             
                # Channel used to sync with upstream collection
         
     | 
| 
         @@ -50,8 +50,21 @@ class CableNotifications.Collection 
     | 
|
| 
       50 
50 
     | 
    
         
             
                # Stores records that needs to be tracked when inserted into the collection
         
     | 
| 
       51 
51 
     | 
    
         
             
                @trackedRecords = []
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
      
 53 
     | 
    
         
            +
                @callbacks = {}
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                @observeChanges(callbacks)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
       53 
57 
     | 
    
         
             
                @callbacks?.initialize?.call(this)
         
     | 
| 
       54 
58 
     | 
    
         | 
| 
      
 59 
     | 
    
         
            +
              # Update the callback stack for collection
         
     | 
| 
      
 60 
     | 
    
         
            +
              observeChanges: (new_callbacks) ->
         
     | 
| 
      
 61 
     | 
    
         
            +
                _.each(new_callbacks, (cb, name) =>
         
     | 
| 
      
 62 
     | 
    
         
            +
                  old_cb = @callbacks?[name]
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @callbacks[name] = () ->
         
     | 
| 
      
 64 
     | 
    
         
            +
                    cb.apply(this, arguments)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    old_cb?.apply(this, arguments)
         
     | 
| 
      
 66 
     | 
    
         
            +
                )
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
       55 
68 
     | 
    
         
             
              # Sync collection to ActionCable Channel
         
     | 
| 
       56 
69 
     | 
    
         
             
              syncToChannel: (@channel) ->
         
     | 
| 
       57 
70 
     | 
    
         
             
                @sync = true
         
     | 
| 
         @@ -93,7 +106,7 @@ class CableNotifications.Collection 
     | 
|
| 
       93 
106 
     | 
    
         
             
                  record
         
     | 
| 
       94 
107 
     | 
    
         | 
| 
       95 
108 
     | 
    
         
             
              # Creates a new record
         
     | 
| 
       96 
     | 
    
         
            -
              create: (fields={}) ->
         
     | 
| 
      
 109 
     | 
    
         
            +
              create: (fields={}, options={}) ->
         
     | 
| 
       97 
110 
     | 
    
         
             
                record = _.find(@data, {id: fields.id})
         
     | 
| 
       98 
111 
     | 
    
         
             
                if record
         
     | 
| 
       99 
112 
     | 
    
         
             
                  console.warn("[create] Not expected to find an existing record with id #{fields.id}")
         
     | 
| 
         @@ -108,6 +121,7 @@ class CableNotifications.Collection 
     | 
|
| 
       108 
121 
     | 
    
         
             
                if !@sync
         
     | 
| 
       109 
122 
     | 
    
         
             
                  @data.push (fields)
         
     | 
| 
       110 
123 
     | 
    
         
             
                  @callbacks?.create?.call(this, fields)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  @callbacks?.changed?.call(this, @data) unless options.batching
         
     | 
| 
       111 
125 
     | 
    
         | 
| 
       112 
126 
     | 
    
         
             
                upstream.call(this, "create", {fields: fields})
         
     | 
| 
       113 
127 
     | 
    
         
             
                fields
         
     | 
| 
         @@ -117,20 +131,21 @@ class CableNotifications.Collection 
     | 
|
| 
       117 
131 
     | 
    
         
             
                record = _.find(@data, selector)
         
     | 
| 
       118 
132 
     | 
    
         
             
                if !record
         
     | 
| 
       119 
133 
     | 
    
         
             
                  if options.upsert
         
     | 
| 
       120 
     | 
    
         
            -
                    @create(fields)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    @create(fields, options)
         
     | 
| 
       121 
135 
     | 
    
         
             
                  else
         
     | 
| 
       122 
136 
     | 
    
         
             
                    console.warn("[update] Couldn't find a matching record:", selector)
         
     | 
| 
       123 
137 
     | 
    
         
             
                else
         
     | 
| 
       124 
138 
     | 
    
         
             
                  if !@sync
         
     | 
| 
       125 
139 
     | 
    
         
             
                    @callbacks?.update?.call(this, selector, fields, options)
         
     | 
| 
       126 
140 
     | 
    
         
             
                    _.extend(record, fields)
         
     | 
| 
      
 141 
     | 
    
         
            +
                    @callbacks?.changed?.call(this, @data) unless options.batching
         
     | 
| 
       127 
142 
     | 
    
         | 
| 
       128 
143 
     | 
    
         
             
                  upstream.call(this, "update", {id: record.id, fields: fields})
         
     | 
| 
       129 
144 
     | 
    
         
             
                  record
         
     | 
| 
       130 
145 
     | 
    
         | 
| 
       131 
146 
     | 
    
         
             
              # Update an existing record or inserts a new one if there is no match
         
     | 
| 
       132 
     | 
    
         
            -
              upsert: (selector={}, fields) ->
         
     | 
| 
       133 
     | 
    
         
            -
                @update(selector, fields, {upsert: true})
         
     | 
| 
      
 147 
     | 
    
         
            +
              upsert: (selector={}, fields, options={}) ->
         
     | 
| 
      
 148 
     | 
    
         
            +
                @update(selector, fields, _.extend(options, {upsert: true}))
         
     | 
| 
       134 
149 
     | 
    
         | 
| 
       135 
150 
     | 
    
         
             
              # Destroy an existing record
         
     | 
| 
       136 
151 
     | 
    
         
             
              destroy: (selector={}) ->
         
     | 
| 
         @@ -142,6 +157,7 @@ class CableNotifications.Collection 
     | 
|
| 
       142 
157 
     | 
    
         
             
                  if !@sync
         
     | 
| 
       143 
158 
     | 
    
         
             
                    @data.splice(index, 1)
         
     | 
| 
       144 
159 
     | 
    
         
             
                    @callbacks?.destroy?.call(this, selector)
         
     | 
| 
      
 160 
     | 
    
         
            +
                    @callbacks?.changed?.call(this, @data) unless options.batching
         
     | 
| 
       145 
161 
     | 
    
         | 
| 
       146 
162 
     | 
    
         
             
                  upstream.call(this, "destroy", {id: record.id})
         
     | 
| 
       147 
163 
     | 
    
         
             
                  record
         
     | 
| 
         @@ -15,15 +15,15 @@ class CableNotifications.Store.DefaultCallbacks 
     | 
|
| 
       15 
15 
     | 
    
         
             
                collection.update({id: packet.id}, packet.data)
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
              update_many: (packet, collection) ->
         
     | 
| 
       18 
     | 
    
         
            -
                _.each packet.data, (fields) ->
         
     | 
| 
       19 
     | 
    
         
            -
                  collection.update({id: fields.id}, fields)
         
     | 
| 
      
 18 
     | 
    
         
            +
                _.each packet.data, (fields, index, records) ->
         
     | 
| 
      
 19 
     | 
    
         
            +
                  collection.update({id: fields.id}, fields, {batching: index<records.length-1})
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
              upsert: (packet, collection) ->
         
     | 
| 
       22 
22 
     | 
    
         
             
                collection.upsert({id: packet.id}, packet.data)
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
              upsert_many: (packet, collection) ->
         
     | 
| 
       25 
     | 
    
         
            -
                _.each packet.data, (fields) ->
         
     | 
| 
       26 
     | 
    
         
            -
                  collection.upsert({id: fields.id}, fields)
         
     | 
| 
      
 25 
     | 
    
         
            +
                _.each packet.data, (fields, index, records) ->
         
     | 
| 
      
 26 
     | 
    
         
            +
                  collection.upsert({id: fields.id}, fields, {batching: index<records.length-1})
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
28 
     | 
    
         
             
              destroy: (packet, collection) ->
         
     | 
| 
       29 
29 
     | 
    
         
             
                collection.destroy({id: packet.id})
         
     | 
| 
         @@ -16,10 +16,10 @@ class CableNotifications.Store 
     | 
|
| 
       16 
16 
     | 
    
         
             
              # Then call original callback
         
     | 
| 
       17 
17 
     | 
    
         
             
              packetReceived = (channelInfo) ->
         
     | 
| 
       18 
18 
     | 
    
         
             
                (packet) ->
         
     | 
| 
       19 
     | 
    
         
            -
                  if packet?. 
     | 
| 
      
 19 
     | 
    
         
            +
                  if packet?.publication
         
     | 
| 
       20 
20 
     | 
    
         
             
                    # Search if there is a collection in this Store that receives packets from the server
         
     | 
| 
       21 
21 
     | 
    
         
             
                    collection = _.find(channelInfo.collections,
         
     | 
| 
       22 
     | 
    
         
            -
                      { 
     | 
| 
      
 22 
     | 
    
         
            +
                      {publication: packet.publication})
         
     | 
| 
       23 
23 
     | 
    
         
             
                    if collection
         
     | 
| 
       24 
24 
     | 
    
         
             
                      dispatchPacket.call(this, packet, collection)
         
     | 
| 
       25 
25 
     | 
    
         
             
                  channelInfo.callbacks.received?.apply(channelInfo.channel, arguments)
         
     | 
| 
         @@ -56,12 +56,11 @@ class CableNotifications.Store 
     | 
|
| 
       56 
56 
     | 
    
         
             
              #######################################
         
     | 
| 
       57 
57 
     | 
    
         | 
| 
       58 
58 
     | 
    
         
             
              # Register a new collection
         
     | 
| 
       59 
     | 
    
         
            -
              registerCollection: (name, channel,  
     | 
| 
       60 
     | 
    
         
            -
                tableName = name unless tableName
         
     | 
| 
      
 59 
     | 
    
         
            +
              registerCollection: (name, channel, publication=name, actions) ->
         
     | 
| 
       61 
60 
     | 
    
         
             
                if @collections[name]
         
     | 
| 
       62 
61 
     | 
    
         
             
                  console.warn "[registerCollection]: Collection '#{name}' already exists"
         
     | 
| 
       63 
62 
     | 
    
         
             
                else
         
     | 
| 
       64 
     | 
    
         
            -
                  @collections[name] = new CableNotifications.Collection(this, name,  
     | 
| 
      
 63 
     | 
    
         
            +
                  @collections[name] = new CableNotifications.Collection(this, name, publication, actions)
         
     | 
| 
       65 
64 
     | 
    
         
             
                  if channel
         
     | 
| 
       66 
65 
     | 
    
         
             
                    @syncToChannel(channel, @collections[name])
         
     | 
| 
       67 
66 
     | 
    
         | 
| 
         @@ -18,42 +18,46 @@ module ActionCableNotifications 
     | 
|
| 
       18 
18 
     | 
    
         
             
                #
         
     | 
| 
       19 
19 
     | 
    
         
             
                # @param [Hash] data Contains command to be executed and its parameters
         
     | 
| 
       20 
20 
     | 
    
         
             
                # {
         
     | 
| 
       21 
     | 
    
         
            -
                #   " 
     | 
| 
      
 21 
     | 
    
         
            +
                #   "publication": "model.model_name.name"
         
     | 
| 
       22 
22 
     | 
    
         
             
                #   "command": "fetch"
         
     | 
| 
       23 
23 
     | 
    
         
             
                #   "params": {}
         
     | 
| 
       24 
24 
     | 
    
         
             
                # }
         
     | 
| 
       25 
25 
     | 
    
         
             
                def action(data)
         
     | 
| 
       26 
26 
     | 
    
         
             
                  data.deep_symbolize_keys!
         
     | 
| 
       27 
27 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                   
     | 
| 
      
 28 
     | 
    
         
            +
                  publication = data[:publication]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  channel_options = @ChannelPublications[publication]
         
     | 
| 
       29 
30 
     | 
    
         
             
                  if channel_options
         
     | 
| 
       30 
31 
     | 
    
         
             
                    model = channel_options[:model]
         
     | 
| 
       31 
     | 
    
         
            -
                     
     | 
| 
       32 
     | 
    
         
            -
                     
     | 
| 
      
 32 
     | 
    
         
            +
                    model_options = model.ChannelPublications[publication]
         
     | 
| 
      
 33 
     | 
    
         
            +
                    params = data[:params]
         
     | 
| 
      
 34 
     | 
    
         
            +
                    command = data[:command]
         
     | 
| 
       33 
35 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                     
     | 
| 
      
 36 
     | 
    
         
            +
                    action_params = {
         
     | 
| 
      
 37 
     | 
    
         
            +
                      publication: publication,
         
     | 
| 
       35 
38 
     | 
    
         
             
                      model: model,
         
     | 
| 
       36 
39 
     | 
    
         
             
                      model_options: model_options,
         
     | 
| 
       37 
     | 
    
         
            -
                       
     | 
| 
       38 
     | 
    
         
            -
                       
     | 
| 
      
 40 
     | 
    
         
            +
                      options: channel_options,
         
     | 
| 
      
 41 
     | 
    
         
            +
                      params: params,
         
     | 
| 
      
 42 
     | 
    
         
            +
                      command: command
         
     | 
| 
       39 
43 
     | 
    
         
             
                    }
         
     | 
| 
       40 
44 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
                    case  
     | 
| 
      
 45 
     | 
    
         
            +
                    case command
         
     | 
| 
       42 
46 
     | 
    
         
             
                    when "fetch"
         
     | 
| 
       43 
     | 
    
         
            -
                      fetch( 
     | 
| 
      
 47 
     | 
    
         
            +
                      fetch(action_params)
         
     | 
| 
       44 
48 
     | 
    
         
             
                    when "create"
         
     | 
| 
       45 
     | 
    
         
            -
                      create( 
     | 
| 
      
 49 
     | 
    
         
            +
                      create(action_params)
         
     | 
| 
       46 
50 
     | 
    
         
             
                    when "update"
         
     | 
| 
       47 
     | 
    
         
            -
                      update( 
     | 
| 
      
 51 
     | 
    
         
            +
                      update(action_params)
         
     | 
| 
       48 
52 
     | 
    
         
             
                    when "destroy"
         
     | 
| 
       49 
     | 
    
         
            -
                      destroy( 
     | 
| 
      
 53 
     | 
    
         
            +
                      destroy(action_params)
         
     | 
| 
       50 
54 
     | 
    
         
             
                    end
         
     | 
| 
       51 
55 
     | 
    
         
             
                  else
         
     | 
| 
       52 
56 
     | 
    
         
             
                    response = {
         
     | 
| 
       53 
     | 
    
         
            -
                       
     | 
| 
      
 57 
     | 
    
         
            +
                      publication: publication,
         
     | 
| 
       54 
58 
     | 
    
         
             
                      msg: 'error',
         
     | 
| 
       55 
     | 
    
         
            -
                      command:  
     | 
| 
       56 
     | 
    
         
            -
                      error: " 
     | 
| 
      
 59 
     | 
    
         
            +
                      command: command,
         
     | 
| 
      
 60 
     | 
    
         
            +
                      error: "Stream for publication '#{publication}' does not exist in channel '#{self.channel_name}'."
         
     | 
| 
       57 
61 
     | 
    
         
             
                    }
         
     | 
| 
       58 
62 
     | 
    
         | 
| 
       59 
63 
     | 
    
         
             
                    # Send error notification to the client
         
     | 
| 
         @@ -63,7 +67,7 @@ module ActionCableNotifications 
     | 
|
| 
       63 
67 
     | 
    
         | 
| 
       64 
68 
     | 
    
         
             
                def initialize(*args)
         
     | 
| 
       65 
69 
     | 
    
         
             
                  @collections = {}
         
     | 
| 
       66 
     | 
    
         
            -
                  @ 
     | 
| 
      
 70 
     | 
    
         
            +
                  @ChannelPublications = {}
         
     | 
| 
       67 
71 
     | 
    
         
             
                  super
         
     | 
| 
       68 
72 
     | 
    
         
             
                end
         
     | 
| 
       69 
73 
     | 
    
         | 
| 
         @@ -92,38 +96,45 @@ module ActionCableNotifications 
     | 
|
| 
       92 
96 
     | 
    
         
             
                # @param [Hash] options Streaming options
         
     | 
| 
       93 
97 
     | 
    
         
             
                #
         
     | 
| 
       94 
98 
     | 
    
         
             
                def stream_notifications_for(model, options = {})
         
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                  # Default publication options
         
     | 
| 
       96 
101 
     | 
    
         
             
                  options = {
         
     | 
| 
       97 
     | 
    
         
            -
                     
     | 
| 
       98 
     | 
    
         
            -
                    params: params,
         
     | 
| 
      
 102 
     | 
    
         
            +
                    publication: model.model_name.name,
         
     | 
| 
       99 
103 
     | 
    
         
             
                    cache: false,
         
     | 
| 
       100 
104 
     | 
    
         
             
                    model_options: {},
         
     | 
| 
       101 
     | 
    
         
            -
                     
     | 
| 
       102 
     | 
    
         
            -
                  }.merge(options)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    scope: :all
         
     | 
| 
      
 106 
     | 
    
         
            +
                  }.merge(options).merge(params.deep_symbolize_keys)
         
     | 
| 
       103 
107 
     | 
    
         | 
| 
       104 
108 
     | 
    
         
             
                  # These options cannot be overridden
         
     | 
| 
       105 
109 
     | 
    
         
             
                  options[:model] = model
         
     | 
| 
       106 
     | 
    
         
            -
                  # options[:channel] = self
         
     | 
| 
       107 
     | 
    
         
            -
                  model_name = model.model_name.collection
         
     | 
| 
       108 
110 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
                   
     | 
| 
       110 
     | 
    
         
            -
                  @ActionCableNotificationsOptions[model_name] = options
         
     | 
| 
      
 111 
     | 
    
         
            +
                  publication = options[:publication]
         
     | 
| 
       111 
112 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                  # Checks if  
     | 
| 
       113 
     | 
    
         
            -
                  if  
     | 
| 
       114 
     | 
    
         
            -
                     
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
      
 113 
     | 
    
         
            +
                  # Checks if the publication already exists in the channel
         
     | 
| 
      
 114 
     | 
    
         
            +
                  if not @ChannelPublications.include?(publication)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    # Sets channel options
         
     | 
| 
      
 116 
     | 
    
         
            +
                    @ChannelPublications[publication] = options
         
     | 
| 
       116 
117 
     | 
    
         | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
      
 118 
     | 
    
         
            +
                    # Checks if model already includes notification callbacks
         
     | 
| 
      
 119 
     | 
    
         
            +
                    if !model.respond_to? :ChannelPublications
         
     | 
| 
      
 120 
     | 
    
         
            +
                      model.send('include', ActionCableNotifications::Model)
         
     | 
| 
      
 121 
     | 
    
         
            +
                    end
         
     | 
| 
       121 
122 
     | 
    
         | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
      
 123 
     | 
    
         
            +
                    # Sets broadcast options if they are not already present in the model
         
     | 
| 
      
 124 
     | 
    
         
            +
                    if not model.ChannelPublications.key? publication
         
     | 
| 
      
 125 
     | 
    
         
            +
                      model.broadcast_notifications_from publication, options[:model_options]
         
     | 
| 
      
 126 
     | 
    
         
            +
                    else # Reads options configuracion from model
         
     | 
| 
      
 127 
     | 
    
         
            +
                      options[:model_options] = model.ChannelPublications[publication]
         
     | 
| 
      
 128 
     | 
    
         
            +
                    end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                    # Start streaming
         
     | 
| 
      
 131 
     | 
    
         
            +
                    stream_from publication, coder: ActiveSupport::JSON do |packet|
         
     | 
| 
      
 132 
     | 
    
         
            +
                      packet.merge!({publication: publication})
         
     | 
| 
      
 133 
     | 
    
         
            +
                      transmit_packet(packet, options)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    end
         
     | 
| 
      
 135 
     | 
    
         
            +
                    # XXX: Transmit initial data
         
     | 
| 
       126 
136 
     | 
    
         | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
       127 
138 
     | 
    
         
             
                end
         
     | 
| 
       128 
139 
     | 
    
         | 
| 
       129 
140 
     | 
    
         
             
                #
         
     | 
| 
         @@ -137,14 +148,16 @@ module ActionCableNotifications 
     | 
|
| 
       137 
148 
     | 
    
         
             
                    cache: false
         
     | 
| 
       138 
149 
     | 
    
         
             
                  }.merge(options)
         
     | 
| 
       139 
150 
     | 
    
         | 
| 
       140 
     | 
    
         
            -
                  packet = packet.as_json.deep_symbolize_keys 
     | 
| 
      
 151 
     | 
    
         
            +
                  packet = packet.as_json.deep_symbolize_keys
         
     | 
| 
       141 
152 
     | 
    
         | 
| 
       142 
     | 
    
         
            -
                  if options 
     | 
| 
       143 
     | 
    
         
            -
                    if  
     | 
| 
      
 153 
     | 
    
         
            +
                  if validate_packet(packet, options)
         
     | 
| 
      
 154 
     | 
    
         
            +
                    if options[:cache]==true
         
     | 
| 
      
 155 
     | 
    
         
            +
                      if update_cache(packet)
         
     | 
| 
      
 156 
     | 
    
         
            +
                        transmit packet
         
     | 
| 
      
 157 
     | 
    
         
            +
                      end
         
     | 
| 
      
 158 
     | 
    
         
            +
                    else
         
     | 
| 
       144 
159 
     | 
    
         
             
                      transmit packet
         
     | 
| 
       145 
160 
     | 
    
         
             
                    end
         
     | 
| 
       146 
     | 
    
         
            -
                  else
         
     | 
| 
       147 
     | 
    
         
            -
                    transmit packet
         
     | 
| 
       148 
161 
     | 
    
         
             
                  end
         
     | 
| 
       149 
162 
     | 
    
         
             
                end
         
     | 
| 
       150 
163 
     | 
    
         | 
| 
         @@ -21,12 +21,13 @@ module ActionCableNotifications 
     | 
|
| 
       21 
21 
     | 
    
         
             
                                to_a() rescue []
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
                      response = {
         
     | 
| 
       24 
     | 
    
         
            -
                         
     | 
| 
      
 24 
     | 
    
         
            +
                        publication: data[:publication],
         
     | 
| 
       25 
25 
     | 
    
         
             
                        msg: 'upsert_many',
         
     | 
| 
       26 
26 
     | 
    
         
             
                        data: results
         
     | 
| 
       27 
27 
     | 
    
         
             
                      }
         
     | 
| 
       28 
28 
     | 
    
         
             
                    rescue Exception => e
         
     | 
| 
       29 
29 
     | 
    
         
             
                      response = {
         
     | 
| 
      
 30 
     | 
    
         
            +
                        publication: data[:publication],
         
     | 
| 
       30 
31 
     | 
    
         
             
                        collection: data[:model].model_name.collection,
         
     | 
| 
       31 
32 
     | 
    
         
             
                        msg: 'error',
         
     | 
| 
       32 
33 
     | 
    
         
             
                        command: data[:command],
         
     | 
| 
         @@ -35,7 +36,7 @@ module ActionCableNotifications 
     | 
|
| 
       35 
36 
     | 
    
         
             
                    end
         
     | 
| 
       36 
37 
     | 
    
         | 
| 
       37 
38 
     | 
    
         
             
                    # Send data to the client
         
     | 
| 
       38 
     | 
    
         
            -
                    transmit_packet response
         
     | 
| 
      
 39 
     | 
    
         
            +
                    transmit_packet response, data[:options]
         
     | 
| 
       39 
40 
     | 
    
         
             
                  end
         
     | 
| 
       40 
41 
     | 
    
         | 
| 
       41 
42 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -1,7 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'action_cable_notifications/hash_db.rb'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module ActionCableNotifications
         
     | 
| 
       2 
4 
     | 
    
         
             
              module Channel
         
     | 
| 
       3 
5 
     | 
    
         
             
                module Cache
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(*args)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    super
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @cache = HashDB::Base.new()
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  #
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # Validates packet before transmitting the message
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # @param [Hash] packet Packet to be transmitted
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # @param [Hash] options Channels options used to validate the packet
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #
         
     | 
| 
      
 18 
     | 
    
         
            +
                  # @return [Boolean] <description>
         
     | 
| 
      
 19 
     | 
    
         
            +
                  #
         
     | 
| 
      
 20 
     | 
    
         
            +
                  def validate_packet(packet, options = {})
         
     | 
| 
      
 21 
     | 
    
         
            +
                    options = {
         
     | 
| 
      
 22 
     | 
    
         
            +
                    }.merge(options)
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    if packet[:msg].in? ['upsert_many', 'create', 'update', 'destroy']
         
     | 
| 
      
 25 
     | 
    
         
            +
                      if packet[:msg].in? ['upsert_many']
         
     | 
| 
      
 26 
     | 
    
         
            +
                        data = packet[:data]
         
     | 
| 
      
 27 
     | 
    
         
            +
                      else
         
     | 
| 
      
 28 
     | 
    
         
            +
                        data = [(packet[:data] || {}).merge({id: packet[:id]})]
         
     | 
| 
      
 29 
     | 
    
         
            +
                      end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                      packet_validator = HashDB::Base.new(data)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      data = packet_validator.scoped_collection(options[:scope]).data
         
     | 
| 
      
 33 
     | 
    
         
            +
                      if data.present?
         
     | 
| 
      
 34 
     | 
    
         
            +
                        if packet[:msg].in? ['upsert_many']
         
     | 
| 
      
 35 
     | 
    
         
            +
                          packet[:data] = data
         
     | 
| 
      
 36 
     | 
    
         
            +
                        else
         
     | 
| 
      
 37 
     | 
    
         
            +
                          packet[:data] = data.first
         
     | 
| 
      
 38 
     | 
    
         
            +
                        end
         
     | 
| 
      
 39 
     | 
    
         
            +
                        true
         
     | 
| 
      
 40 
     | 
    
         
            +
                      else
         
     | 
| 
      
 41 
     | 
    
         
            +
                        false
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    else
         
     | 
| 
      
 44 
     | 
    
         
            +
                      true
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
       5 
49 
     | 
    
         
             
                  #
         
     | 
| 
       6 
50 
     | 
    
         
             
                  # Updates server side cache of client side collections
         
     | 
| 
       7 
51 
     | 
    
         
             
                  # XXX compute cache diff before sending to clients
         
     | 
| 
         @@ -0,0 +1,111 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module HashDB
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Base
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize(data=nil)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  if data.present?
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @data = Array(data)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  else
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @data = []
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def data
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @data
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def data=(data)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @data = data || []
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def wrap(data)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  HashDB::Base.new(data)
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                private :wrap
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def all(options={})
         
     | 
| 
      
 27 
     | 
    
         
            +
                  if options.has_key?(:conditions)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    where(options[:conditions])
         
     | 
| 
      
 29 
     | 
    
         
            +
                  else
         
     | 
| 
      
 30 
     | 
    
         
            +
                    wrap(@data ||= [])
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def count
         
     | 
| 
      
 35 
     | 
    
         
            +
                  all.length
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def where(options)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  return @data if options.blank?
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  data = (@data || []).select do |record|
         
     | 
| 
      
 42 
     | 
    
         
            +
                    match_options?(record, options)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  wrap(data)
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def match_options?(record, options)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  options.all? do |col, match|
         
     | 
| 
      
 50 
     | 
    
         
            +
                    if [Array, Range].include?(match.class)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      match.include?(record[col])
         
     | 
| 
      
 52 
     | 
    
         
            +
                    else
         
     | 
| 
      
 53 
     | 
    
         
            +
                      record[col] == match
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                private :match_options?
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def scoped_collection ( scope = :all )
         
     | 
| 
      
 61 
     | 
    
         
            +
                  scope = scope.to_a if scope.is_a? Hash
         
     | 
| 
      
 62 
     | 
    
         
            +
                  Array(scope).inject(self) do |o, a|
         
     | 
| 
      
 63 
     | 
    
         
            +
                    o.try(*a)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                def select( fields=nil )
         
     | 
| 
      
 68 
     | 
    
         
            +
                  if fields.present?
         
     | 
| 
      
 69 
     | 
    
         
            +
                    wrap(@data.map{|v| v.slice(*(Array(fields).map(&:to_sym)))})
         
     | 
| 
      
 70 
     | 
    
         
            +
                  else
         
     | 
| 
      
 71 
     | 
    
         
            +
                    all
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                def limit( count=nil )
         
     | 
| 
      
 76 
     | 
    
         
            +
                  if count.present? and count>0
         
     | 
| 
      
 77 
     | 
    
         
            +
                    wrap(@data.slice(0,count))
         
     | 
| 
      
 78 
     | 
    
         
            +
                  else
         
     | 
| 
      
 79 
     | 
    
         
            +
                    all
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                def delete_all
         
     | 
| 
      
 84 
     | 
    
         
            +
                  @data = []
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                def first
         
     | 
| 
      
 88 
     | 
    
         
            +
                  @data.first
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                def last
         
     | 
| 
      
 92 
     | 
    
         
            +
                  @data.last
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                def find(id, * args)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  case id
         
     | 
| 
      
 97 
     | 
    
         
            +
                    when nil
         
     | 
| 
      
 98 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 99 
     | 
    
         
            +
                    when :all
         
     | 
| 
      
 100 
     | 
    
         
            +
                      all
         
     | 
| 
      
 101 
     | 
    
         
            +
                    when :first
         
     | 
| 
      
 102 
     | 
    
         
            +
                      all(*args).first
         
     | 
| 
      
 103 
     | 
    
         
            +
                    when Array
         
     | 
| 
      
 104 
     | 
    
         
            +
                      id.map { |i| find(i) }
         
     | 
| 
      
 105 
     | 
    
         
            +
                    else
         
     | 
| 
      
 106 
     | 
    
         
            +
                      where({id: id})
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -4,8 +4,8 @@ module ActionCableNotifications 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                included do
         
     | 
| 
       6 
6 
     | 
    
         
             
                  # Action cable notification options storage
         
     | 
| 
       7 
     | 
    
         
            -
                  class_attribute : 
     | 
| 
       8 
     | 
    
         
            -
                  self. 
     | 
| 
      
 7 
     | 
    
         
            +
                  class_attribute :ChannelPublications
         
     | 
| 
      
 8 
     | 
    
         
            +
                  self.ChannelPublications = {}
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                  # Register Callbacks
         
     | 
| 
       11 
11 
     | 
    
         
             
                  before_update :prepare_update
         
     | 
| 
         @@ -19,19 +19,19 @@ module ActionCableNotifications 
     | 
|
| 
       19 
19 
     | 
    
         
             
                  #
         
     | 
| 
       20 
20 
     | 
    
         
             
                  # Sets or removes notificacions options for Active Record model
         
     | 
| 
       21 
21 
     | 
    
         
             
                  #
         
     | 
| 
       22 
     | 
    
         
            -
                  # @param [sym]  
     | 
| 
      
 22 
     | 
    
         
            +
                  # @param [sym] publication Topic name to broadcast in
         
     | 
| 
       23 
23 
     | 
    
         
             
                  # @param [hash] options Hash containing notification options
         
     | 
| 
       24 
24 
     | 
    
         
             
                  #
         
     | 
| 
       25 
     | 
    
         
            -
                  def broadcast_notifications_from (  
     | 
| 
      
 25 
     | 
    
         
            +
                  def broadcast_notifications_from ( publication, options = {} )
         
     | 
| 
       26 
26 
     | 
    
         
             
                    # Default options
         
     | 
| 
       27 
27 
     | 
    
         
             
                    options = {
         
     | 
| 
       28 
28 
     | 
    
         
             
                      actions: [:create, :update, :destroy],
         
     | 
| 
       29 
     | 
    
         
            -
                      track_scope_changes:  
     | 
| 
      
 29 
     | 
    
         
            +
                      track_scope_changes: false,
         
     | 
| 
       30 
30 
     | 
    
         
             
                      scope: :all,             # Default collection scope
         
     | 
| 
       31 
31 
     | 
    
         
             
                      records: []
         
     | 
| 
       32 
32 
     | 
    
         
             
                      }.merge(options)
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                    self. 
     | 
| 
      
 34 
     | 
    
         
            +
                    self.ChannelPublications[publication.to_s] = options
         
     | 
| 
       35 
35 
     | 
    
         
             
                  end
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
       37 
37 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -50,19 +50,17 @@ module ActionCableNotifications 
     | 
|
| 
       50 
50 
     | 
    
         
             
                  #
         
     | 
| 
       51 
51 
     | 
    
         
             
                  # Retrieves initial values to be sent to clients upon subscription
         
     | 
| 
       52 
52 
     | 
    
         
             
                  #
         
     | 
| 
       53 
     | 
    
         
            -
                  # @param [Sym]  
     | 
| 
      
 53 
     | 
    
         
            +
                  # @param [Sym] publication Name of publication stream
         
     | 
| 
       54 
54 
     | 
    
         
             
                  #
         
     | 
| 
       55 
55 
     | 
    
         
             
                  # @return [Hash] Hash containing the results in the following format:
         
     | 
| 
       56 
56 
     | 
    
         
             
                  # {
         
     | 
| 
       57 
     | 
    
         
            -
                  #   collection: self.model_name.collection,
         
     | 
| 
       58 
57 
     | 
    
         
             
                  #   msg: 'add_collection',
         
     | 
| 
       59 
58 
     | 
    
         
             
                  #   data: self.scoped_collection(options[:scope])
         
     | 
| 
       60 
59 
     | 
    
         
             
                  # }
         
     | 
| 
       61 
     | 
    
         
            -
                  def notify_initial (  
     | 
| 
       62 
     | 
    
         
            -
                    options = self. 
     | 
| 
      
 60 
     | 
    
         
            +
                  def notify_initial ( publication )
         
     | 
| 
      
 61 
     | 
    
         
            +
                    options = self.ChannelPublications[publication.to_s]
         
     | 
| 
       63 
62 
     | 
    
         
             
                    if options.present?
         
     | 
| 
       64 
63 
     | 
    
         
             
                      {
         
     | 
| 
       65 
     | 
    
         
            -
                        collection: self.model_name.collection,
         
     | 
| 
       66 
64 
     | 
    
         
             
                        msg: 'upsert_many',
         
     | 
| 
       67 
65 
     | 
    
         
             
                        data: self.scoped_collection(options[:scope])
         
     | 
| 
       68 
66 
     | 
    
         
             
                      }
         
     | 
| 
         @@ -74,12 +72,11 @@ module ActionCableNotifications 
     | 
|
| 
       74 
72 
     | 
    
         
             
                # Broadcast notifications when a new record is created
         
     | 
| 
       75 
73 
     | 
    
         
             
                #
         
     | 
| 
       76 
74 
     | 
    
         
             
                def notify_create
         
     | 
| 
       77 
     | 
    
         
            -
                  self. 
     | 
| 
      
 75 
     | 
    
         
            +
                  self.ChannelPublications.each do |publication, options|
         
     | 
| 
       78 
76 
     | 
    
         
             
                    if options[:actions].include? :create
         
     | 
| 
       79 
77 
     | 
    
         
             
                      # Checks if record is within scope before broadcasting
         
     | 
| 
       80 
78 
     | 
    
         
             
                      if options[:scope]==:all or self.class.scoped_collection(options[:scope]).where(id: self.id).present?
         
     | 
| 
       81 
     | 
    
         
            -
                        ActionCable.server.broadcast  
     | 
| 
       82 
     | 
    
         
            -
                          collection: self.model_name.collection,
         
     | 
| 
      
 79 
     | 
    
         
            +
                        ActionCable.server.broadcast publication,
         
     | 
| 
       83 
80 
     | 
    
         
             
                          msg: 'create',
         
     | 
| 
       84 
81 
     | 
    
         
             
                          id: self.id,
         
     | 
| 
       85 
82 
     | 
    
         
             
                          data: self
         
     | 
| 
         @@ -89,7 +86,7 @@ module ActionCableNotifications 
     | 
|
| 
       89 
86 
     | 
    
         
             
                end
         
     | 
| 
       90 
87 
     | 
    
         | 
| 
       91 
88 
     | 
    
         
             
                def prepare_update
         
     | 
| 
       92 
     | 
    
         
            -
                  self. 
     | 
| 
      
 89 
     | 
    
         
            +
                  self.ChannelPublications.each do |publication, options|
         
     | 
| 
       93 
90 
     | 
    
         
             
                    if options[:actions].include? :update
         
     | 
| 
       94 
91 
     | 
    
         
             
                      if options[:scope]==:all
         
     | 
| 
       95 
92 
     | 
    
         
             
                        options[:records].push self
         
     | 
| 
         @@ -108,9 +105,16 @@ module ActionCableNotifications 
     | 
|
| 
       108 
105 
     | 
    
         
             
                # if they are within configured scope
         
     | 
| 
       109 
106 
     | 
    
         
             
                #
         
     | 
| 
       110 
107 
     | 
    
         
             
                def notify_update
         
     | 
| 
      
 108 
     | 
    
         
            +
                  # Get model changes
         
     | 
| 
      
 109 
     | 
    
         
            +
                  if self.respond_to?(:saved_changes) # For Rails >= 5.1
         
     | 
| 
      
 110 
     | 
    
         
            +
                    changes = self.saved_changes.transform_values(&:second)
         
     | 
| 
      
 111 
     | 
    
         
            +
                  else # For Rails < 5.1
         
     | 
| 
      
 112 
     | 
    
         
            +
                    changes = self.changes.transform_values(&:second)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
       111 
115 
     | 
    
         
             
                  # Checks if there are changes in the model
         
     | 
| 
       112 
     | 
    
         
            -
                  if ! 
     | 
| 
       113 
     | 
    
         
            -
                    self. 
     | 
| 
      
 116 
     | 
    
         
            +
                  if !changes.empty?
         
     | 
| 
      
 117 
     | 
    
         
            +
                    self.ChannelPublications.each do |publication, options|
         
     | 
| 
       114 
118 
     | 
    
         
             
                      if options[:actions].include? :update
         
     | 
| 
       115 
119 
     | 
    
         
             
                        # Checks if previous record was within scope
         
     | 
| 
       116 
120 
     | 
    
         
             
                        record = options[:records].detect{|r| r.id==self.id}
         
     | 
| 
         @@ -136,24 +140,24 @@ module ActionCableNotifications 
     | 
|
| 
       136 
140 
     | 
    
         | 
| 
       137 
141 
     | 
    
         
             
                        # Broadcasts notifications about model changes
         
     | 
| 
       138 
142 
     | 
    
         
             
                        if is_in_scope
         
     | 
| 
       139 
     | 
    
         
            -
                           
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                            if record.respond_to?(k)
         
     | 
| 
       143 
     | 
    
         
            -
                              changes[k] = v[1]
         
     | 
| 
       144 
     | 
    
         
            -
                            end
         
     | 
| 
       145 
     | 
    
         
            -
                          end
         
     | 
| 
      
 143 
     | 
    
         
            +
                          if was_in_scope
         
     | 
| 
      
 144 
     | 
    
         
            +
                            # Get model changes and applies them to the scoped collection record
         
     | 
| 
      
 145 
     | 
    
         
            +
                            changes.select!{|k,v| record.respond_to?(k)}
         
     | 
| 
       146 
146 
     | 
    
         | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
      
 147 
     | 
    
         
            +
                            if !changes.empty?
         
     | 
| 
      
 148 
     | 
    
         
            +
                              ActionCable.server.broadcast publication,
         
     | 
| 
      
 149 
     | 
    
         
            +
                                msg: 'update',
         
     | 
| 
      
 150 
     | 
    
         
            +
                                id: self.id,
         
     | 
| 
      
 151 
     | 
    
         
            +
                                data: changes
         
     | 
| 
      
 152 
     | 
    
         
            +
                            end
         
     | 
| 
      
 153 
     | 
    
         
            +
                          else
         
     | 
| 
      
 154 
     | 
    
         
            +
                            ActionCable.server.broadcast publication,
         
     | 
| 
      
 155 
     | 
    
         
            +
                              msg: 'create',
         
     | 
| 
      
 156 
     | 
    
         
            +
                              id: record.id,
         
     | 
| 
      
 157 
     | 
    
         
            +
                              data: record
         
     | 
| 
       153 
158 
     | 
    
         
             
                          end
         
     | 
| 
       154 
159 
     | 
    
         
             
                        elsif was_in_scope # checks if needs to delete the record if its no longer in scope
         
     | 
| 
       155 
     | 
    
         
            -
                          ActionCable.server.broadcast  
     | 
| 
       156 
     | 
    
         
            -
                            collection: self.model_name.collection,
         
     | 
| 
      
 160 
     | 
    
         
            +
                          ActionCable.server.broadcast publication,
         
     | 
| 
       157 
161 
     | 
    
         
             
                            msg: 'destroy',
         
     | 
| 
       158 
162 
     | 
    
         
             
                            id: self.id
         
     | 
| 
       159 
163 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -166,12 +170,11 @@ module ActionCableNotifications 
     | 
|
| 
       166 
170 
     | 
    
         
             
                # Broadcast notifications when a record is destroyed.
         
     | 
| 
       167 
171 
     | 
    
         
             
                #
         
     | 
| 
       168 
172 
     | 
    
         
             
                def notify_destroy
         
     | 
| 
       169 
     | 
    
         
            -
                  self. 
     | 
| 
      
 173 
     | 
    
         
            +
                  self.ChannelPublications.each do |publication, options|
         
     | 
| 
       170 
174 
     | 
    
         
             
                    if options[:scope]==:all or options[:actions].include? :destroy
         
     | 
| 
       171 
175 
     | 
    
         
             
                      # Checks if record is within scope before broadcasting
         
     | 
| 
       172 
176 
     | 
    
         
             
                      if options[:scope]==:all or self.class.scoped_collection(options[:scope]).where(id: self.id).present?
         
     | 
| 
       173 
     | 
    
         
            -
                        ActionCable.server.broadcast  
     | 
| 
       174 
     | 
    
         
            -
                          collection: self.model_name.collection,
         
     | 
| 
      
 177 
     | 
    
         
            +
                        ActionCable.server.broadcast publication,
         
     | 
| 
       175 
178 
     | 
    
         
             
                          msg: 'destroy',
         
     | 
| 
       176 
179 
     | 
    
         
             
                          id: self.id
         
     | 
| 
       177 
180 
     | 
    
         
             
                      end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,22 +1,19 @@ 
     | 
|
| 
       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.30
         
     | 
| 
       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: 2017-05- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2017-05-19 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rails
         
     | 
| 
       15 
15 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       16 
16 
     | 
    
         
             
                requirements:
         
     | 
| 
       17 
     | 
    
         
            -
                - - "~>"
         
     | 
| 
       18 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       19 
     | 
    
         
            -
                    version: 5.0.0
         
     | 
| 
       20 
17 
     | 
    
         
             
                - - ">="
         
     | 
| 
       21 
18 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       22 
19 
     | 
    
         
             
                    version: 5.0.0.1
         
     | 
| 
         @@ -24,9 +21,6 @@ dependencies: 
     | 
|
| 
       24 
21 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       25 
22 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       26 
23 
     | 
    
         
             
                requirements:
         
     | 
| 
       27 
     | 
    
         
            -
                - - "~>"
         
     | 
| 
       28 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       29 
     | 
    
         
            -
                    version: 5.0.0
         
     | 
| 
       30 
24 
     | 
    
         
             
                - - ">="
         
     | 
| 
       31 
25 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       32 
26 
     | 
    
         
             
                    version: 5.0.0.1
         
     | 
| 
         @@ -34,14 +28,14 @@ dependencies: 
     | 
|
| 
       34 
28 
     | 
    
         
             
              name: lodash-rails
         
     | 
| 
       35 
29 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       36 
30 
     | 
    
         
             
                requirements:
         
     | 
| 
       37 
     | 
    
         
            -
                - - " 
     | 
| 
      
 31 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       38 
32 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       39 
33 
     | 
    
         
             
                    version: 4.15.0
         
     | 
| 
       40 
34 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       41 
35 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       42 
36 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       43 
37 
     | 
    
         
             
                requirements:
         
     | 
| 
       44 
     | 
    
         
            -
                - - " 
     | 
| 
      
 38 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       45 
39 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       46 
40 
     | 
    
         
             
                    version: 4.15.0
         
     | 
| 
       47 
41 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
         @@ -132,6 +126,7 @@ files: 
     | 
|
| 
       132 
126 
     | 
    
         
             
            - lib/action_cable_notifications/channel_actions.rb
         
     | 
| 
       133 
127 
     | 
    
         
             
            - lib/action_cable_notifications/channel_cache.rb
         
     | 
| 
       134 
128 
     | 
    
         
             
            - lib/action_cable_notifications/engine.rb
         
     | 
| 
      
 129 
     | 
    
         
            +
            - lib/action_cable_notifications/hash_db.rb
         
     | 
| 
       135 
130 
     | 
    
         
             
            - lib/action_cable_notifications/model.rb
         
     | 
| 
       136 
131 
     | 
    
         
             
            - lib/action_cable_notifications/version.rb
         
     | 
| 
       137 
132 
     | 
    
         
             
            - lib/tasks/action_cable_notifications_tasks.rake
         
     |