def change_counter_cache(obj, options)
      change_counter_column = options.fetch(:counter_column) { counter_cache_name_for(obj) }

      # default to the current foreign key value
      id_to_change = foreign_key_value(obj, relation, options[:was])
      # allow overwriting of foreign key value by the caller
      id_to_change = foreign_key_values.call(id_to_change) if foreign_key_values

      if id_to_change && change_counter_column
        delta_magnitude = if delta_column
                            (options[:was] ? attribute_was(obj, delta_column) : obj.public_send(delta_column)) || 0
                          else
                            counter_delta_magnitude_for(obj)
                          end
        # increment or decrement?
        operator = options[:increment] ? '+' : '-'

        # we don't use Rails' update_counters because we support changing the timestamp
        quoted_column = model.connection.quote_column_name(change_counter_column)

        updates = []
        # this updates the actual counter
        updates << "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{delta_magnitude}"
        # and here we update the timestamp, if so desired
        if touch
          current_time = obj.send(:current_time_from_proper_timezone)
          timestamp_columns = obj.send(:timestamp_attributes_for_update_in_model)
          timestamp_columns << touch if touch != true
          timestamp_columns.each do |timestamp_column|
            updates << "#{timestamp_column} = '#{current_time.to_formatted_s(:db)}'"
          end
        end

        klass = relation_klass(relation, source: obj, was: options[:was])
        primary_key = relation_primary_key(relation, source: obj, was: options[:was])

        if @with_papertrail
          instance = klass.where(primary_key => id_to_change).first
          if instance
            if instance.paper_trail.respond_to?(:save_with_version)
              # touch_with_version is deprecated starting in PaperTrail 9.0.0

              current_time = obj.send(:current_time_from_proper_timezone)
              timestamp_columns = obj.send(:timestamp_attributes_for_update_in_model)
              timestamp_columns.each do |timestamp_column|
                instance.send("#{timestamp_column}=", current_time)
              end

              instance.paper_trail.save_with_version(validate: false)
            else
              instance.paper_trail.touch_with_version
            end
          end
        end

        klass.where(primary_key => id_to_change).update_all updates.join(', ')
      end
    end
def change_counter_cache(obj, options)
      change_counter_column = options.fetch(:counter_column) { counter_cache_name_for(obj) }

      # default to the current foreign key value
      id_to_change = foreign_key_value(obj, relation, options[:was])
      # allow overwriting of foreign key value by the caller
      id_to_change = foreign_key_values.call(id_to_change) if foreign_key_values

      if id_to_change && change_counter_column
        delta_magnitude = if delta_column
                            (options[:was] ? attribute_was(obj, delta_column) : obj.public_send(delta_column)) || 0
                          else
                            counter_delta_magnitude_for(obj)
                          end
        # increment or decrement?
        operator = options[:increment] ? '+' : '-'

        # we don't use Rails' update_counters because we support changing the timestamp
        quoted_column = model.connection.quote_column_name(change_counter_column)

        updates = []
        # this updates the actual counter
        updates << "#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{delta_magnitude}"
        # and here we update the timestamp, if so desired
        if touch
          current_time = obj.send(:current_time_from_proper_timezone)
          timestamp_columns = obj.send(:timestamp_attributes_for_update_in_model)
          timestamp_columns << touch if touch != true
          timestamp_columns.each do |timestamp_column|
            updates << "#{timestamp_column} = '#{current_time.to_formatted_s(:db)}'"
          end
        end

        klass = relation_klass(relation, source: obj, was: options[:was])
        primary_key = relation_primary_key(relation, source: obj, was: options[:was])

        if @with_papertrail
          instance = klass.where(primary_key => id_to_change).first
          if instance
            if instance.paper_trail.respond_to?(:save_with_version)
              # touch_with_version is deprecated starting in PaperTrail 9.0.0

              current_time = obj.send(:current_time_from_proper_timezone)
              timestamp_columns = obj.send(:timestamp_attributes_for_update_in_model)
              timestamp_columns.each do |timestamp_column|
                instance.send("#{timestamp_column}=", current_time)
              end

              instance.paper_trail.save_with_version(validate: false)
            else
              instance.paper_trail.touch_with_version
            end
          end
        end

        klass.where(primary_key => id_to_change).update_all updates.join(', ')
      end
    end
increments or decrements a counter cache

 options:
   :increment => true to increment, false to decrement
   :relation => which relation to increment the count on,
   :counter_cache_name => the column name of the counter cache
   :counter_column => overrides :counter_cache_name
   :delta_column => override the default count delta (1) with the value of this column in the counted record
   :was => whether to get the current value or the old value of the
      first part of the relation
   :with_papertrail => update the column via Papertrail touch_with_version method