class ScopedSearch::Definition

The ScopedSearch definition class defines on what fields should be search in the model in what cases

A definition can be created by calling the scoped_search method on an ActiveRecord-based class, so you should not create an instance of this class yourself.

Constants

INTEGER_REGXP
NUMERICAL_REGXP

Attributes

default_order[RW]
klass[R]
profile[RW]

Public Instance Methods

default_fields() click to toggle source

Returns a list of fields that should be searched on by default.

Every field will show up in this method’s result, except for fields for which the only_explicit parameter is set to true.

# File lib/scoped_search/definition.rb, line 226
def default_fields
  unique_fields.reject { |field| field.only_explicit }
end
default_fields_for(value, operator = nil) click to toggle source

Returns a list of appropriate fields to search in given a search keyword and operator.

# File lib/scoped_search/definition.rb, line 200
def default_fields_for(value, operator = nil)

  column_types  = []
  column_types += [:string, :text]                      if [nil, :like, :unlike, :ne, :eq].include?(operator)
  column_types += [:double, :float, :decimal] if value =~ NUMERICAL_REGXP
  column_types += [:integer] if value =~ INTEGER_REGXP
  column_types += [:datetime, :date, :timestamp]        if (parse_temporal(value))

  default_fields.select { |field| column_types.include?(field.type) && !field.set? }
end
define(options) click to toggle source

Defines a new search field for this search definition.

# File lib/scoped_search/definition.rb, line 231
def define(options)
  Field.new(self, options)
end
field_by_name(name) click to toggle source

this method return definitions::field object from string

# File lib/scoped_search/definition.rb, line 175
def field_by_name(name)
  field = fields[name.to_sym] unless name.blank?
  if field.nil?
    dotted = name.to_s.split('.')[0]
    field = fields[dotted.to_sym] unless dotted.nil?
  end
  field
end
fields() click to toggle source
# File lib/scoped_search/definition.rb, line 164
def fields
  @profile ||= :default
  @profile_fields[@profile] ||= {}
end
operator_by_field_name(name) click to toggle source

this method is used by the syntax auto completer to suggest operators.

# File lib/scoped_search/definition.rb, line 185
def operator_by_field_name(name)
  field = field_by_name(name)
  return [] if field.nil?
  return field.operators                                   if field.operators
  return ['= ', '!= ']                                     if field.set?
  return ['= ', '> ', '< ', '<= ', '>= ','!= ', '^ ', '!^ '] if field.numerical?
  return ['= ', '!= ', '~ ', '!~ ', '^ ', '!^ ']             if field.textual?
  return ['= ', '> ', '< ']                                if field.temporal?
  raise ScopedSearch::QueryNotSupported, "could not verify '#{name}' type, this can be a result of a definition error"
end
parse_temporal(value) click to toggle source

Try to parse a string as a datetime. Supported formats are Today, Yesterday, Sunday, ‘1 day ago’, ‘2 hours ago’, ‘3 months ago’,‘Jan 23, 2004’ And many more formats that are documented in Ruby DateTime API Doc.

# File lib/scoped_search/definition.rb, line 214
def parse_temporal(value)
  return Date.current if value =~ %r\btoday\b/
  return 1.day.ago.to_date if value =~ %r\byesterday\b/
  return (eval(value.strip.gsub(%r\s+/,'.').downcase)).to_datetime if value =~ %r\A\s*\d+\s+\bhours?|minutes?\b\s+\bago\b\s*\z/
  return (eval(value.strip.gsub(%r\s+/,'.').downcase)).to_date if value =~ %r\A\s*\d+\s+\b(days?|weeks?|months?|years?)\b\s+\bago\b\s*\z/
  DateTime.parse(value, true) rescue nil
end
unique_fields() click to toggle source
# File lib/scoped_search/definition.rb, line 169
def unique_fields
  @profile ||= :default
  @profile_unique_fields[@profile] ||= []
end

Protected Instance Methods

register_complete_for!() click to toggle source

Registers the ::complete_for method within the class that is used for searching.

# File lib/scoped_search/definition.rb, line 262
def register_complete_for! # :nodoc
  @klass.class_eval do
    def self.complete_for(query, options = {})
      ScopedSearch::AutoCompleteBuilder.auto_complete(@scoped_search , query, options)
    end
  end
end
register_named_scope!() click to toggle source

Registers the search_for named scope within the class that is used for searching.

# File lib/scoped_search/definition.rb, line 238
def register_named_scope! # :nodoc
  if @klass.ancestors.include?(ActiveRecord::Base)
    case ActiveRecord::VERSION::MAJOR
    when 2
      @klass.named_scope(:search_for, lambda { |*args| ScopedSearch::QueryBuilder.build_query(self, args[0], args[1]) })
    when 3
      @klass.scope(:search_for, lambda { |*args|
        find_options = ScopedSearch::QueryBuilder.build_query(self, args[0], args[1])
        search_scope = @klass.scoped
        search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions]
        search_scope = search_scope.includes(find_options[:include]) if find_options[:include]
        search_scope = search_scope.joins(find_options[:joins]) if find_options[:joins]
        search_scope = search_scope.reorder(find_options[:order]) if find_options[:order]
        search_scope
      })
    else
      raise "This ActiveRecord version is currently not supported!"
    end
  else
    raise "Currently, only ActiveRecord 2.1 or higher is supported!"
  end
end

Public Class Methods

new(klass) click to toggle source

Initializes a ScopedSearch definition instance. This method will also setup a database adapter and create the :search_for named scope if it does not yet exist.

# File lib/scoped_search/definition.rb, line 149
def initialize(klass)
  @klass                 = klass
  @fields                = {}
  @unique_fields         = []
  @profile_fields        = {:default => {}}
  @profile_unique_fields = {:default => []}


  register_named_scope! unless klass.respond_to?(:search_for)
  register_complete_for! unless klass.respond_to?(:complete_for)

end

Protected Class Methods

complete_for(query, options = {}) click to toggle source
# File lib/scoped_search/definition.rb, line 264
def self.complete_for(query, options = {})
  ScopedSearch::AutoCompleteBuilder.auto_complete(@scoped_search , query, options)
end