module FiltersControllerAddOn::ClassMethods

Public Class Methods

execute_order(value, scope, keys, args, desc) click to toggle source
# File lib/spyro/filters_controller_add_on.rb, line 115
def self.execute_order value, scope, keys, args, desc
  value = keys.first unless keys.include? value.to_sym

  my_scope = args.find {|arg| arg.is_a?(Hash) and arg[value.to_sym]}
  scope = if my_scope
    scope.instance_exec &(my_scope[value.to_sym])
  else
    scope.order(value.to_sym)
  end

  if desc
    scope = (scope.respond_to?(:desc) ? scope.desc : scope.reverse_order)
  end
  scope = execute_order(keys.first, scope, keys, args, ordered_options[:default] == :desc) unless value.to_sym == keys.first.to_sym

  return scope
end

Public Instance Methods

filtered(*args) click to toggle source
# File lib/spyro/filters_controller_add_on.rb, line 82
def filtered *args #filter=campus:Cluj;
  cattr_accessor :filtered_keys
  cattr_accessor :filtered_values
  cattr_accessor :filtered_args

  args = args.map {|arg| arg.is_a?(Hash) ? arg.to_a[0] : [arg, nil]}.to_h
  self.filtered_keys = args.keys
  self.filtered_values = self.filtered_keys.map {|k| [k, (args[k] ? args[k][1].call : resource_class.pluck(k).uniq)] }.to_h
  self.filtered_args = args

  has_scope :filter, :only => [:index] do |controller, scope, values|
    values.split(";").each do |value|
      name, filter = *value.split(':', 2)
      if name.to_sym.in? args.keys
        scopes = args[name.to_sym]
        if scopes
          scope = scope.instance_exec(filter.split(','), &(scopes[0]))
        else
          scope = scope.where(name => filter.split(','))
        end
      end
    end

    scope
  end
end
ordered(*args) click to toggle source
# File lib/spyro/filters_controller_add_on.rb, line 110
def ordered *args
  cattr_accessor :ordered_keys
  cattr_accessor :ordered_options

  self.ordered_options = (args.count > 1 ? args.extract_options! : {})
  def self.execute_order value, scope, keys, args, desc
    value = keys.first unless keys.include? value.to_sym

    my_scope = args.find {|arg| arg.is_a?(Hash) and arg[value.to_sym]}
    scope = if my_scope
      scope.instance_exec &(my_scope[value.to_sym])
    else
      scope.order(value.to_sym)
    end

    if desc
      scope = (scope.respond_to?(:desc) ? scope.desc : scope.reverse_order)
    end
    scope = execute_order(keys.first, scope, keys, args, ordered_options[:default] == :desc) unless value.to_sym == keys.first.to_sym

    return scope
  end

  args = [*args].flatten
  keys = args.flat_map {|arg| arg.is_a?(Hash) ? arg.map(&:first) : arg}.map(&:to_sym)
  self.ordered_keys = keys

  raise "Missing params" if keys.empty? or (keys.length == 1 and keys.first.to_sym == :default)
  raise "Bad value for default" if self.ordered_options and !self.ordered_options[:default].in? [nil, :desc]

  has_scope :order, :default => keys.first.to_s, :only => [:index], as: :sort do |controller, scope, value|
    if !controller.params[:sort].blank? or controller.params[:rev_sort].blank?
      execute_order(value, scope, keys, args, false).send((controller.params[:sort].nil? and self.ordered_options[:default] == :desc) ? :desc : :all)
    else
      scope.all
    end
  end

  has_scope :rev_order, :default => keys.first.to_s, :only => [:index], as: :rev_sort do |controller, scope, value|
    if !controller.params[:rev_sort].blank? and controller.params[:sort].blank?
      execute_order(value, scope, keys, args, true)
    else
      scope.all
    end
  end
end
paginate() click to toggle source
# File lib/spyro/filters_controller_add_on.rb, line 12
def paginate
  has_scope :page, :default => 1, :only => [:index], :if => lambda {|c| (c.params[:format].try(:to_sym) || :html).in? [:html, :js] }
end
paginated() click to toggle source
# File lib/spyro/filters_controller_add_on.rb, line 16
def paginated
  paginate
end
ranged(*args) click to toggle source
# File lib/spyro/filters_controller_add_on.rb, line 53
def ranged *args
  cattr_accessor :ranged_keys
  cattr_accessor :ranged_values
  cattr_accessor :ranged_args

  args = args.map {|arg| arg.is_a?(Hash) ? arg.to_a[0] : [arg, nil]}.to_h
  self.ranged_keys = args.keys
  self.ranged_values = self.ranged_keys.map {|k| [k, (args[k] ? args[k][2].call : resource_class.min_max(k))] }.to_h
  self.ranged_args = args

  has_scope :range, :only => [:index] do |controller, scope, values| #http://localhost:3000/exams?range=created_at:2015-06-03%2000:00%3bmax_people:50,100&sort=name
    values.split(";").each do |value|
      name, min, max = *value.match(/(\w+):([^,]+)?,?([^,]+)?/).values_at(1, 2, 3)
      if name.to_sym.in? args.keys
        scopes = args[name.to_sym]
        if scopes
          scope = scope.instance_exec(min, &(scopes[0])) if min
          scope = scope.instance_exec(max, &(scopes[1])) if max
        else
          scope = scope.where("#{resource_class.table_name}.#{name} >= ?", min) if min
          scope = scope.where("#{resource_class.table_name}.#{name} <= ?", max) if max
        end
      end
    end

    scope
  end
end
searched(*args) click to toggle source

in:name CPP in:campus a

# File lib/spyro/filters_controller_add_on.rb, line 21
def searched *args # recode moi avec `or` avec Rails 5 :'(
  cattr_accessor :searched_keys
  cattr_accessor :searched_args

  self.searched_keys = args.map {|arg| (arg.is_a?(Hash) ? arg.to_a[0].first : arg)}
  self.searched_args = args

  has_scope :search, :only => [:index] do |controller, scope, values|
    sql = values.reverse.split(/\s+(?!\S+:\S+)/).map(&:reverse).reverse.map do |value| # feinte du variable-length look behind
      in_search, value = value.match(/(in:(?<filter>\S+)\s+)?(?<search>.+)/).values_at 1, 2

      sql = args.map do |arg|
        key = (arg.is_a?(Hash) ? arg.to_a[0].first : arg)
        next if !in_search.nil? and in_search != key.to_s

        if arg.is_a? Hash
          scope.instance_exec(value, &(arg.to_a[0].last)).to_sql
        else
          scope.where("#{resource_class.table_name}.#{arg} ilike ?", "%#{value}%").to_sql
        end
      end.reject(&:blank?)

      sql = (sql.any? ? sql.join(' UNION ') : scope.where("1=0").to_sql)
      resource_class.from("(#{sql}) #{resource_class.table_name}").to_sql
    end

    sql = (sql.any? ? sql.join(' INTERSECT ') : scope.where("1=0").to_sql)

    resource_class.from("(#{sql}) #{resource_class.table_name}")
  end
end