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
Public Class Methods
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 157 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
Public Instance Methods
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 232 def default_fields unique_fields.reject { |field| field.only_explicit } end
Returns a list of appropriate fields to search in given a search keyword and operator.
# File lib/scoped_search/definition.rb, line 206 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
Defines a new search field for this search definition.
# File lib/scoped_search/definition.rb, line 237 def define(options) Field.new(self, options) end
this method return definitions::field object from string
# File lib/scoped_search/definition.rb, line 181 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.blank? end field end
# File lib/scoped_search/definition.rb, line 170 def fields @profile ||= :default @profile_fields[@profile] ||= {} end
this method is used by the syntax auto completer to suggest operators.
# File lib/scoped_search/definition.rb, line 191 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, "Unsupported type '#{field.type.inspect}')' for field '#{name}'. This can be a result of a search definition problem." end
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 220 def parse_temporal(value) return Date.current if value =~ /\btoday\b/i return 1.day.ago.to_date if value =~ /\byesterday\b/i return (eval($1.strip.gsub(/\s+/,'.').downcase)).to_datetime if value =~ /\A\s*(\d+\s+\b(?:hours?|minutes?)\b\s+\bago)\b\s*\z/i return (eval($1.strip.gsub(/\s+/,'.').downcase)).to_date if value =~ /\A\s*(\d+\s+\b(?:days?|weeks?|months?|years?)\b\s+\bago)\b\s*\z/i DateTime.parse(value, true) rescue nil end
Returns a reflection for a given klass and name
# File lib/scoped_search/definition.rb, line 242 def reflection_by_name(klass, name) return if name.nil? klass.reflections[name.to_sym] || klass.reflections[name.to_s] end
# File lib/scoped_search/definition.rb, line 175 def unique_fields @profile ||= :default @profile_unique_fields[@profile] ||= [] end
Protected Instance Methods
Registers the complete_for method within the class that is used for searching.
# File lib/scoped_search/definition.rb, line 267 def register_complete_for! # :nodoc @klass.extend(ScopedSearch::AutoCompleteClassMethods) end
Registers the search_for named scope within the class that is used for searching.
# File lib/scoped_search/definition.rb, line 250 def register_named_scope! # :nodoc definition = self @klass.scope(:search_for, proc { |query, options| search_scope = ActiveRecord::VERSION::MAJOR == 3 ? @klass.scoped : (ActiveRecord::VERSION::MINOR < 1 ? @klass.where(nil) : @klass.all) find_options = ScopedSearch::QueryBuilder.build_query(definition, query || '', options || {}) 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 = search_scope.references(find_options[:include]) if find_options[:include] && ActiveRecord::VERSION::MAJOR >= 4 search_scope }) end