module Autoscope::ActiveRecordMethods::ClassMethods

Public Instance Methods

add_scopes(params, scope = self.all) click to toggle source

adds any available scopes to the scope passed in

@example

class MyController < ActionController::Base
  # GET /my_resources.json
  def index
    @my_resources = MyResource.add_scopes(params)
  end
end

@param params [Hash] @param scope [ActiveRecord::Relation] @return [ActiveRecord::Relation]

# File lib/autoscope/active_record_methods.rb, line 38
def add_scopes(params, scope = self.all)
  params = params.with_indifferent_access

  # add any type parameters
  scope = self.add_type_filter(params, scope)
  # add our static scopes
  scope = self.add_static_scopes(params, scope)
  scope = self.add_dynamic_scopes(params, scope)
  scope = self.add_pagination(params, scope)
  scope
end
scope_definition() click to toggle source

Scope definition

@return [Hash] Definition

# File lib/autoscope/active_record_methods.rb, line 54
def scope_definition
  self.stored_scope_definition.clone.tap do |ret|
    self.scope_class_methods.each do |meth|
      ret[meth] = self.get_scope_parameters(self.method(meth))
    end
  end
end

Protected Instance Methods

add_dynamic_scopes(params, scope = self.all) click to toggle source

adds scopes that take parameters to the scope passed in

@param params [Hash] @param scope [ActiveRecord::Relation] @return [ActiveRecord::Relation]

@example

class MyController < ActionController::Base
  # GET /my_resources.json
  def index
    @my_resources = MyResource.add_static_scopes(params)
  end
end
# File lib/autoscope/active_record_methods.rb, line 129
def add_dynamic_scopes(params, scope = self.all)
  scope.klass.dynamic_scopes.each_pair do |scope_name, arg_def|

    # skip scopes that are not defined
    next if self.blank_param?(params[scope_name])

    # now apply the arguments
    args_to_pass = self.get_dynamic_scope_args(
      scope_name,
      arg_def,
      params[scope_name]
    )

    # actually apply the scope
    scope = scope.send(scope_name, *args_to_pass)
  end

  # return the final scope
  scope
end
add_pagination(params, scope = self.all) click to toggle source

Add pagination if it is supplied in the params

@param params [Hash] @param scope = self.all [ActiveRecord::Relation]

@return [ActiveRecord::Relation]

# File lib/autoscope/active_record_methods.rb, line 157
def add_pagination(params, scope = self.all)
  if params[:page] || params[:per_page]
    scope = scope.paginate(
      page: params[:page] || 1,
      per_page: params[:per_page] || 20
    )
  end
  return scope
end
add_static_scopes(params, scope = self.all) click to toggle source

adds scopes that don’t take any parameters to the scope passed in

@example

class MyController < ActionController::Base
  # GET /my_resources.json
  def index
    @my_resources = MyResource.add_static_scopes(params)
  end
end

@param params [Hash] @param scope [ActiveRecord::Relation] @return [ActiveRecord::Relation]

# File lib/autoscope/active_record_methods.rb, line 78
def add_static_scopes(params, scope = self.all)
  scope.klass.static_scopes.each do |scope_name|
    if params[scope_name].present?
      scope = scope.send(scope_name)
    end
  end
  # special case for ids
  if params[:ids].present?
    scope = scope.where(id: params[:ids])
  end
  scope
end
add_type_filter(params, scope) click to toggle source
# File lib/autoscope/active_record_methods.rb, line 91
def add_type_filter(params, scope)
  return scope unless params[:type].present?

  # get the class - rescuing an invalid class name
  begin
    klass = params[:type].constantize

    # if we have been given a class that is not a subclass
    # we should return the original scope

    unless self.descendants.include?(klass)
      logger.error("#{klass} is not a descendant of #{self}")
      return scope
    end

    # merge in our old scope and return
    klass.all.merge(scope)
  rescue NameError => e
    logger.error(e.message)
    logger.error(e.backtrace.pretty_inspect)
    return scope
  end
end
blank_param?(data) click to toggle source

Is this data blank?

@param data [String, Hash]

@return [Boolean]

# File lib/autoscope/active_record_methods.rb, line 173
def blank_param?(data)
  data.blank? || data.try(:values).try(:all?, &:blank?)
end
dynamic_scopes() click to toggle source

list of all scopes that take an argument

@return [Hash<Symbol, Hash>]

# File lib/autoscope/active_record_methods.rb, line 271
def dynamic_scopes
  self.scope_definition.select { |_k, v| v.present? }
end
get_dynamic_scope_args(scope_name, arg_def, params) click to toggle source

Get the appropriate args from dynamic scopes

@param scope_name [String, Symbol] @param arg_def [Hash{Symbol, Symbol}] Proc args definition @param params [Hash] Relevant params

@return [Array] Array of args to send to the scope

# File lib/autoscope/active_record_methods.rb, line 185
def get_dynamic_scope_args(scope_name, arg_def, params)
  [].tap do |ret|
    # arg def tells us which args are required
    arg_def.each_pair do |arg_name, arg_type|
      case arg_type.to_sym
        # this argument is required
        when :req
          ret << params[arg_name]
        when :opt
          unless params[arg_name].nil?
            ret << params[arg_name]
          end
        when :rest
          ret.concat(Array.wrap(params[arg_name]))
      end
    end
  end
end
get_scope_parameters(proc) click to toggle source

Helper to extract scope options into something usable in a resource definition

@param proc [Proc] Scope proc

@return [Hash<Symbol,Symbol>]

# File lib/autoscope/active_record_methods.rb, line 211
def get_scope_parameters(proc)
  params = {}
  proc.parameters.each do |type, param|
    params[param] = type
  end
  params
end
has_scopes(*scopes) click to toggle source

Method to denote that we have class methods of that are really scopes

@param *scopes [Array<Symbol,String>]

@return [Array<Symbol>]

# File lib/autoscope/active_record_methods.rb, line 226
def has_scopes(*scopes)
  self.scope_class_methods = self.scope_class_methods +
    Array.wrap(scopes).map(&:to_sym)
end
protected_scope(*args) click to toggle source

Set up a regular scope, but mark it as protected (not visible via the api)

@param [Array<Mixed>] Args to create a scope

@return [Class] self

# File lib/autoscope/active_record_methods.rb, line 238
def protected_scope(*args)
  self.scope_without_resource_definition_addition(*args)
end
scope_with_resource_definition_addition(name, opts = {}, &block) click to toggle source

set up a regular scope, making it visibule to the API

# File lib/autoscope/active_record_methods.rb, line 245
def scope_with_resource_definition_addition(name, opts = {}, &block)
  # if it's a proc, we figure out its parameters
  params = if opts.is_a?(Proc)
    self.get_scope_parameters(opts)
  # otherwise we just use a blank hash
  else
    {}
  end

  # update scope definition
  self.stored_scope_definition = self.stored_scope_definition.merge(
    name.to_sym => params
  )

  # call the original scope definition method
  self.scope_without_resource_definition_addition(
    name,
    opts,
    &block
  )
end
static_scopes() click to toggle source

list of all scopes that don’t take any arguments

@return [Array<Hash>]

# File lib/autoscope/active_record_methods.rb, line 279
def static_scopes
  scopes = self.scope_definition
    .select { |_k, v| v.blank? }
    .keys
  scopes | [:first, :last, :all]
end