Class | ScopedSearch::Definition |
In: |
lib/scoped_search/definition.rb
|
Parent: | Object |
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.
NUMERICAL_REGXP | = | /^\-?\d+(\.\d+)?$/ |
default_order | [RW] | |
klass | [R] | |
profile | [RW] |
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 140 140: def initialize(klass) 141: @klass = klass 142: @fields = {} 143: @unique_fields = [] 144: @profile_fields = {:default => {}} 145: @profile_unique_fields = {:default => []} 146: 147: 148: register_named_scope! unless klass.respond_to?(:search_for) 149: register_complete_for! unless klass.respond_to?(:complete_for) 150: 151: end
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 215 215: def default_fields 216: unique_fields.reject { |field| field.only_explicit } 217: end
Returns a list of appropriate fields to search in given a search keyword and operator.
# File lib/scoped_search/definition.rb, line 190 190: def default_fields_for(value, operator = nil) 191: 192: column_types = [] 193: column_types += [:string, :text] if [nil, :like, :unlike, :ne, :eq].include?(operator) 194: column_types += [:integer, :double, :float, :decimal] if value =~ NUMERICAL_REGXP 195: column_types += [:datetime, :date, :timestamp] if (parse_temporal(value)) 196: 197: default_fields.select { |field| column_types.include?(field.type) && !field.set? } 198: end
this method return definitions::field object from string
# File lib/scoped_search/definition.rb, line 166 166: def field_by_name(name) 167: field = fields[name.to_sym] unless name.blank? 168: if field.nil? 169: dotted = name.to_s.split('.')[0] 170: field = fields[dotted.to_sym] unless dotted.nil? 171: end 172: field 173: end
# File lib/scoped_search/definition.rb, line 155 155: def fields 156: @profile ||= :default 157: @profile_fields[@profile] ||= {} 158: end
this method is used by the syntax auto completer to suggest operators.
# File lib/scoped_search/definition.rb, line 176 176: def operator_by_field_name(name) 177: field = field_by_name(name) 178: return [] if field.nil? 179: return field.operators if field.operators 180: return ['= ', '!= '] if field.set? 181: return ['= ', '> ', '< ', '<= ', '>= ','!= ', '^ ', '!^ '] if field.numerical? 182: return ['= ', '!= ', '~ ', '!~ ', '^ ', '!^ '] if field.textual? 183: return ['= ', '> ', '< '] if field.temporal? 184: raise ScopedSearch::QueryNotSupported, "could not verify '#{name}' type, this can be a result of a definition error" 185: 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 203 203: def parse_temporal(value) 204: return Date.current if value =~ /\btoday\b/i 205: return 1.day.ago.to_date if value =~ /\byesterday\b/i 206: return (eval(value.strip.gsub(/\s+/,'.').downcase)).to_datetime if value =~ /\A\s*\d+\s+\bhours?|minutes?\b\s+\bago\b\s*\z/i 207: return (eval(value.strip.gsub(/\s+/,'.').downcase)).to_date if value =~ /\A\s*\d+\s+\b(days?|weeks?|months?|years?)\b\s+\bago\b\s*\z/i 208: DateTime.parse(value, true) rescue nil 209: end
# File lib/scoped_search/definition.rb, line 160 160: def unique_fields 161: @profile ||= :default 162: @profile_unique_fields[@profile] ||= [] 163: end
Registers the search_for named scope within the class that is used for searching.
# File lib/scoped_search/definition.rb, line 227 227: def register_named_scope! # :nodoc 228: if @klass.ancestors.include?(ActiveRecord::Base) 229: case ActiveRecord::VERSION::MAJOR 230: when 2 231: @klass.named_scope(:search_for, lambda { |*args| ScopedSearch::QueryBuilder.build_query(self, args[0], args[1]) }) 232: when 3 233: @klass.scope(:search_for, lambda { |*args| 234: find_options = ScopedSearch::QueryBuilder.build_query(self, args[0], args[1]) 235: search_scope = @klass.scoped 236: search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions] 237: search_scope = search_scope.includes(find_options[:include]) if find_options[:include] 238: search_scope = search_scope.joins(find_options[:joins]) if find_options[:joins] 239: search_scope = search_scope.order(find_options[:order]) if find_options[:order] 240: search_scope = search_scope.group(find_options[:group]) if find_options[:group] 241: search_scope 242: }) 243: else 244: raise "This ActiveRecord version is currently not supported!" 245: end 246: else 247: raise "Currently, only ActiveRecord 2.1 or higher is supported!" 248: end 249: end