lib/rating/models/rating/extension.rb
# frozen_string_literal: true
module Rating
module Extension
extend ActiveSupport::Concern
included do
def rate(resource, value, author: self, extra_scopes: {}, metadata: {}, scope: nil)
Rate.create(
author: author,
extra_scopes: extra_scopes,
metadata: metadata,
resource: resource,
scopeable: scope,
value: value
)
end
def rate_for(resource, extra_scopes: {}, scope: nil)
Rate.rate_for author: self, extra_scopes: extra_scopes, resource: resource, scopeable: scope
end
def rated?(resource, extra_scopes: {}, scope: nil)
Rate.exists?(extra_scopes.merge(author: self, resource: resource, scopeable: scope))
end
def rates(extra_scopes: {}, scope: nil)
attributes = { scopeable: scope }.merge(extra_scopes)
rates_records.where attributes
end
def rated(extra_scopes: {}, scope: nil)
attributes = { scopeable: scope }.merge(extra_scopes)
rated_records.where attributes
end
def rating(scope: nil)
rating_records.find_by scopeable: scope
end
def rating_warm_up(scoping: nil)
return Rating.find_or_create_by(resource: self) if scoping.blank?
[scoping].flatten.compact.map do |attribute|
next unless respond_to?(attribute)
[public_send(attribute)].flatten.compact.map do |object|
Rating.find_or_create_by! resource: self, scopeable: object
end
end.flatten.compact
end
end
module ClassMethods
def rating(options = {})
after_create -> { rating_warm_up scoping: options[:scoping] }, unless: -> { options[:as] == :author }
has_many :rating_records,
as: :resource,
class_name: '::Rating::Rating',
dependent: :destroy
has_many :rates_records,
as: :resource,
class_name: '::Rating::Rate',
dependent: :destroy
has_many :rated_records,
as: :author,
class_name: '::Rating::Rate',
dependent: :destroy
scope :order_by_rating, lambda { |opts = {}|
column = opts.fetch(:column, :estimate)
direction = opts.fetch(:direction, :desc)
scope = opts[:scope]
includes(:rating_records)
.where(Rating.table_name => { scopeable_id: scope&.id, scopeable_type: scope&.class&.base_class&.name })
.order("#{Rating.table_name}.#{column} #{direction}")
}
define_method :rating_options do
options
end
end
end
end
end