tonycoco/pusherable

Enabling single push triggering on update_all and destroy_all operations

jdurand opened this issue · 1 comments

@tonycoco, I just wanted to share this bit of code that could be a draft for what could enable triggering pusher just once when doing update_all and destroy_all instead of a push for every updated record.

I'm not yet sure how I feel a about monkey patching ActiveRecord::Relation and ActiveRecord::Associations::CollectionAssociation for this though. It's working we'll for me so far.

What do you think?

module Pusherable
  module Relation
    def pusher_trigger(action, nb_records)
      if klass.pusherable? && nb_records > 0
        resource = klass.name.underscore.pluralize
        Pusher.trigger(klass.pusherable_channel, "#{resource}.#{action}", { resource: resource }.to_json)
      end

      nb_records
    end
  end
end

class ActiveRecord::Relation
  include Pusherable::Relation

  def update_all_with_push(updates)
    now = Time.zone.now

    case updates
      when Hash;   updates.merge!(updated_at: now)
      when String; updates += ", updated_at = '#{now.to_s(:db)}'"
      when Array;  updates[0] += ', updated_at = ?'; updates << now
    end

    return update_all_without_push(updates) unless klass.pusherable?
    klass.deactivate_pusherable_triggers
    nb_records = pusher_trigger :refresh, update_all_without_push(updates)
    klass.activate_pusherable_triggers
    nb_records
  end

  alias_method_chain :update_all, :push unless method_defined? :update_all_without_push
end

class ActiveRecord::Associations::CollectionAssociation
  include Pusherable::Relation

  def destroy_all_with_push
    return destroy_all_without_push unless klass.pusherable?
    klass.deactivate_pusherable_triggers
    nb_records = pusher_trigger :reload, destroy_all_without_push.count
    klass.activate_pusherable_triggers
    nb_records
  end

  alias_method_chain :destroy_all, :push unless method_defined? :destroy_all_without_push
end

@jdurand While this looks great to me, I'm not sure I want to get into the business of supporting monkey-patches :) This might just have to be something that lives in your application. What we could do is document this in the Wiki though. Thanks!