class ScopedFrom::Query

Constants

FALSE_VALUES
ORDER_DIRECTIONS
TRUE_VALUES

Attributes

params[R]

Public Class Methods

new(relation, params, options = {}) click to toggle source

Available options are: - :only : to restrict to specified keys.

- :except : to ignore specified keys.
# File lib/scoped_from/query.rb, line 13
def initialize(relation, params, options = {})
  self.relation = relation
  self.options = options
  self.params = params
end

Public Instance Methods

order_column() click to toggle source
# File lib/scoped_from/query.rb, line 19
def order_column
  parse_order(params['order'])[:column]
end
order_direction() click to toggle source
# File lib/scoped_from/query.rb, line 23
def order_direction
  parse_order(params['order'])[:direction]
end
relation() click to toggle source
# File lib/scoped_from/query.rb, line 27
def relation
  relation = @relation
  params.each do |name, value|
    [value].flatten.each do |value|
      relation = invoke_param(relation, name, value)
    end
  end
  decorate_relation(relation)
end

Protected Instance Methods

decorate_relation(relation) click to toggle source
# File lib/scoped_from/query.rb, line 39
def decorate_relation(relation)
  return relation if relation.respond_to?(:query)
  def relation.query
    @__query
  end
  relation.instance_variable_set('@__query', self)
  relation
end
false?(value) click to toggle source
# File lib/scoped_from/query.rb, line 62
def false?(value)
  FALSE_VALUES.include?(value.to_s.strip.downcase)
end
invoke_param(relation, name, value) click to toggle source
# File lib/scoped_from/query.rb, line 48
def invoke_param(relation, name, value)
  if name.to_s == 'order'
    relation.order(order_to_hash(value))
  elsif relation.scope_with_one_argument?(name)
    relation.send(name, value)
  elsif relation.scope_without_argument?(name)
    relation.send(name)
  elsif relation.column_names.include?(name.to_s)
    relation.where(name => value)
  else
    relation
  end
end
options=(options) click to toggle source
# File lib/scoped_from/query.rb, line 66
def options=(options)
  @options = options.symbolize_keys
end
order_to_hash(value) click to toggle source
# File lib/scoped_from/query.rb, line 70
def order_to_hash(value)
  order = parse_order(value)
  order.present? ? { order[:column] => order[:direction].downcase.to_sym } : {}
end
params=(params) click to toggle source
# File lib/scoped_from/query.rb, line 75
def params=(params)
  params = params.params if params.is_a?(self.class)
  params = CGI.parse(params.to_s) unless params.is_a?(Hash) || defined?(ActionController::Parameters) && params.is_a?(ActionController::Parameters)
  @params = ActiveSupport::HashWithIndifferentAccess.new
  params.each do |name, value|
    values = [value].flatten
    next if values.empty?
    if name.to_s == 'order'
      orders = parse_orders(values).map { |order| "#{order[:column]}.#{order[:direction]}" }
      @params[name] = (orders.many? ? orders : orders.first) if orders.any?
    elsif @relation.scope_without_argument?(name)
      @params[name] = true if values.all? { |value| true?(value) }
    elsif @relation.scope_with_one_argument?(name)
      value = values.many? ? values : values.first
      @params[name] = @params[name] ? [@params[name], value].flatten : value
    elsif @options[:exclude_columns].blank? && @relation.column_names.include?(name.to_s)
      if @relation.columns_hash[name.to_s].type == :boolean
        @params[name] = true if values.all? { |value| true?(value) }
        @params[name] = false if values.all? { |value| false?(value) }
      else
        value = values.many? ? values : values.first
        @params[name] = @params[name] ? [@params[name], value].flatten : value
      end
    end
  end
  @params.slice!(*[@options[:only]].flatten) if @options[:only].present?
  @params.except!(*[@options[:except]].flatten) if @options[:except].present?
end
parse_order(value) click to toggle source
# File lib/scoped_from/query.rb, line 104
def parse_order(value)
  column, direction = value.to_s.split(/[\.:\s]+/, 2)
  direction = direction.to_s.downcase
  direction = ORDER_DIRECTIONS.first unless ORDER_DIRECTIONS.include?(direction)
  @relation.column_names.include?(column) ? { column: column, direction: direction } : {}
end
parse_orders(values) click to toggle source
# File lib/scoped_from/query.rb, line 111
def parse_orders(values)
  [].tap do |orders|
    values.each do |value|
      order = parse_order(value)
      orders << order if order.present? && !orders.any? { |o| o[:column] == order[:column] }
    end
  end
end
relation=(relation) click to toggle source
# File lib/scoped_from/query.rb, line 120
def relation=(relation)
  @relation = relation.is_a?(Class) ? relation.all : relation
end
true?(value) click to toggle source
# File lib/scoped_from/query.rb, line 124
def true?(value)
  TRUE_VALUES.include?(value.to_s.strip.downcase)
end