class Scopie::Base

Public Class Methods

has_scope(*scopes, **options) click to toggle source

Detects params from url and apply as scopes to your classes.

Options

  • :type - Coerces the type of the parameter sent.

  • :only - In which actions the scope is applied.

  • :except - In which actions the scope is not applied.

  • :as - The key in the params hash expected to find the scope.

    Defaults to the scope name.
  • :default - Default value for the scope. Whenever supplied the scope

    is always called.
  • :allow_blank - Blank values are not sent to scopes by default. Set to true to overwrite.

Method usage

You can also define a method having the same name as a scope. The current scope, value and params are yielded to the block so the user can apply the scope on its own. The method can return new scope or the boolean value. In the latter case will be used not modified scope. This is useful in case we need to manipulate the given value:

has_scope :category

def category(scope, value, _hash)
  value != 'all' && scope.by_category(value)
end

has_scope :not_voted_by_me, type: :boolean

def not_voted_by_me(scope, _value, _hash)
  scope.not_voted_by(controller.current_user.id) # The controller method is available in the scopie_rails gem
end
# File lib/scopie/base.rb, line 50
def self.has_scope(*scopes, **options)
  @scopes_configuration ||= {}
  normalize_options!(options)

  scopes.each do |scope|
    @scopes_configuration[scope.to_sym] = options
  end
end
scopes_configuration() click to toggle source
# File lib/scopie/base.rb, line 5
def self.scopes_configuration
  instance_variable_get(:@scopes_configuration) || {}
end

Private Class Methods

normalize_options!(options) click to toggle source
# File lib/scopie/base.rb, line 148
def self.normalize_options!(options)
  [:only, :except].each do |key|
    options[key] = Array(options[key]).map(&:to_s)
    options[key].reject!(&:empty?)
  end

  options
end
reset_scopes_configuration!() click to toggle source
# File lib/scopie/base.rb, line 142
def self.reset_scopes_configuration!
  @scopes_configuration = {}
end

Public Instance Methods

apply_scopes(target, hash, method = nil) click to toggle source
# File lib/scopie/base.rb, line 59
def apply_scopes(target, hash, method = nil)
  current_scopes_values(hash, method).each do |scope_name, value|
    target = apply_scope(scope_name, target, value, hash)
  end

  target
end
current_scopes(hash, method = nil) click to toggle source
# File lib/scopie/base.rb, line 67
def current_scopes(hash, method = nil)
  hsh = current_scopes_values(hash, method)
  hsh.update(hsh) do |_, value|
    value.coerced
  end
end
scopes_configuration() click to toggle source
# File lib/scopie/base.rb, line 9
def scopes_configuration
  self.class.scopes_configuration
end

Private Instance Methods

apply_scope(scope_name, target, value, hash) click to toggle source
# File lib/scopie/base.rb, line 88
def apply_scope(scope_name, target, value, hash)
  result = if respond_to?(scope_name)
             public_send(scope_name, target, value.coerced, hash)
           else
             args = [scope_name]
             args << value.coerced if value.present? || value.allow_blank?
             target.public_send(*args)
           end

  if Scopie::RESULTS_TO_IGNORE.include?(result)
    target
  else
    result
  end
end
current_scopes_values(hash, method) click to toggle source
# File lib/scopie/base.rb, line 76
def current_scopes_values(hash, method)
  scopes = scopes_configuration.map do |scope_name, options|
    value = scope_value(scope_name, options, hash)
    next unless scope_applicable?(value, options, method)

    [scope_name, value]
  end

  scopes.compact!
  scopes.to_h
end
key_name(scope_name, options) click to toggle source
# File lib/scopie/base.rb, line 104
def key_name(scope_name, options)
  key_name = scope_name
  key_name = options[:as] if options.key?(:as)
  key_name
end
method_applicable?(method, options) click to toggle source
# File lib/scopie/base.rb, line 129
def method_applicable?(method, options)
  return true unless method
  action = method.to_s

  methods_white_list = options[:only]
  methods_black_list = options[:except]

  return false if methods_black_list.include?(action)
  return false if methods_white_list.any? && !methods_white_list.include?(action)

  true
end
reduced_hash(hash, options) click to toggle source
# File lib/scopie/base.rb, line 124
def reduced_hash(hash, options)
  return hash unless options.key?(:in)
  hash.fetch(options[:in]) { {} }
end
scope_applicable?(value, options, method) click to toggle source
# File lib/scopie/base.rb, line 117
def scope_applicable?(value, options, method)
  return false unless method_applicable?(method, options)
  return false unless value.given?

  value.present? || !options[:ignore_blank]
end
scope_value(scope_name, options, hash) click to toggle source
# File lib/scopie/base.rb, line 110
def scope_value(scope_name, options, hash)
  key_name = key_name(scope_name, options)
  reduced_hash = reduced_hash(hash, options)

  Scopie::Value.new(reduced_hash, key_name, options)
end