module ActionCableNotifications::Model
Constants
- ChannelPublications
Public Instance Methods
Sets or removes notificacions options for Active Record model
@param [sym] publication Topic name to broadcast in @param [hash] options Hash containing notification options
# File lib/action_cable_notifications/model.rb, line 25 def broadcast_notifications_from ( publication, options = {} ) # Default options options = { actions: [:create, :update, :destroy], track_scope_changes: false, scope: :all, # Default collection scope records: [] }.merge(options) self.ChannelPublications[publication.to_s] = options end
Broadcast notifications when a new record is created
# File lib/action_cable_notifications/model.rb, line 74 def notify_create self.ChannelPublications.each do |publication, options| if options[:actions].include? :create # Checks if record is within scope before broadcasting if options[:scope]==:all or self.class.scoped_collection(options[:scope]).where(id: self.id).present? ActionCable.server.broadcast publication, msg: 'create', id: self.id, data: self end end end end
Broadcast notifications when a record is destroyed.
# File lib/action_cable_notifications/model.rb, line 172 def notify_destroy self.ChannelPublications.each do |publication, options| if options[:scope]==:all or options[:actions].include? :destroy # Checks if record is within scope before broadcasting if options[:scope]==:all or self.class.scoped_collection(options[:scope]).where(id: self.id).present? ActionCable.server.broadcast publication, msg: 'destroy', id: self.id end end end end
Retrieves initial values to be sent to clients upon subscription
@param [Sym] publication Name of publication stream
@return [Hash] Hash containing the results in the following format: {
msg: 'add_collection', data: self.scoped_collection(options[:scope])
}
# File lib/action_cable_notifications/model.rb, line 60 def notify_initial ( publication ) options = self.ChannelPublications[publication.to_s] if options.present? { msg: 'upsert_many', data: self.scoped_collection(options[:scope]) } end end
Broadcast notifications when a record is updated. Only changed fields will be sent if they are within configured scope
# File lib/action_cable_notifications/model.rb, line 107 def notify_update # Get model changes if self.respond_to?(:saved_changes) # For Rails >= 5.1 changes = self.saved_changes.transform_values(&:second) else # For Rails < 5.1 changes = self.changes.transform_values(&:second) end # Checks if there are changes in the model if !changes.empty? self.ChannelPublications.each do |publication, options| if options[:actions].include? :update # Checks if previous record was within scope record = options[:records].detect{|r| r.id==self.id} was_in_scope = record.present? options[:records].delete(record) if was_in_scope # Checks if current record is within scope if options[:track_scope_changes]==true is_in_scope = false if options[:scope]==:all record = self is_in_scope = true else record = self.class.scoped_collection(options[:scope]).where(id: self.id) if record.present? record = record.first is_in_scope = true end end else is_in_scope = was_in_scope end # Broadcasts notifications about model changes if is_in_scope if was_in_scope # Get model changes and applies them to the scoped collection record changes.select!{|k,v| record.respond_to?(k)} if !changes.empty? ActionCable.server.broadcast publication, msg: 'update', id: self.id, data: changes end else ActionCable.server.broadcast publication, msg: 'create', id: record.id, data: record end elsif was_in_scope # checks if needs to delete the record if its no longer in scope ActionCable.server.broadcast publication, msg: 'destroy', id: self.id end end end end end
# File lib/action_cable_notifications/model.rb, line 88 def prepare_update self.ChannelPublications.each do |publication, options| if options[:actions].include? :update if options[:scope]==:all options[:records].push self else record = self.class.scoped_collection(options[:scope]).where(id: self.id) if record.present? options[:records].push record.first end end end end end
Returns collection scoped as specified in parameters.
@param [Array] scope Contains the scopes to be applied. For example: [[:limit, 5], [:order, :id]]
@return [ActiveRecordRelation] Results fetched from the database
# File lib/action_cable_notifications/model.rb, line 45 def scoped_collection ( scope = :all ) scope = scope.to_a if scope.is_a? Hash Array(scope).inject(self) {|o, a| o.try(*a)} rescue nil end