salkar/inkwell

View on GitHub
app/models/concerns/inkwell/can_be_favorited.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

module Inkwell::CanBeFavorited
  extend ActiveSupport::Concern

  included do
    attr_accessor :favorited_in_timeline
    has_one :inkwell_object_counter_cache,
             as: :cached_object,
             class_name: "Inkwell::ObjectCounterCache",
             dependent: :delete
    has_many :inkwell_favorited,
             as: :favorite_object,
             class_name: "Inkwell::Favorite",
             dependent: :delete_all
    before_destroy :inkwell_can_be_favorited_before_destroy, prepend: true

    def favorited_by(&block)
      result = inkwell_favorited
        .includes(favorite_subject: :inkwell_subject_counter_cache)
      result = block.call(result) if block.present?
      result.map(&:favorite_subject)
    end

    def favorited_by?(subject)
      check_favorited_by(subject)
      subject.favorite?(self)
    end

    def favorited_count
      # move to &. when ruby supported version starts 2.3 or upper version
      (inkwell_object_counter_cache &&
        inkwell_object_counter_cache.favorite_count) ||
        inkwell_favorited.count
    end

    private

      def check_favorited_by(obj)
        unless obj.class.try(:inkwell_can_favorite?)
          raise(Inkwell::Errors::CannotFavorite, obj)
        end
      end

      def inkwell_can_be_favorited_before_destroy
        ids = favorited_by.map do |subj|
          subj.try(:inkwell_subject_counter_cache).try(:id)
        end.compact
        Inkwell::SubjectCounterCache.update_counters(
          ids,
          favorite_count: -1)
      end
  end

  module ClassMethods
    def inkwell_can_be_favorited?
      true
    end
  end
end