| 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+)?$/ |
| INTEGER_REGXP | = | /^\-?\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 149
149: def initialize(klass)
150: @klass = klass
151: @fields = {}
152: @unique_fields = []
153: @profile_fields = {:default => {}}
154: @profile_unique_fields = {:default => []}
155:
156:
157: register_named_scope! unless klass.respond_to?(:search_for)
158: register_complete_for! unless klass.respond_to?(:complete_for)
159:
160: end
# File lib/scoped_search/definition.rb, line 264
264: def self.complete_for(query, options = {})
265: ScopedSearch::AutoCompleteBuilder.auto_complete(@scoped_search , query, options)
266: 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 226
226: def default_fields
227: unique_fields.reject { |field| field.only_explicit }
228: end
Returns a list of appropriate fields to search in given a search keyword and operator.
# File lib/scoped_search/definition.rb, line 200
200: def default_fields_for(value, operator = nil)
201:
202: column_types = []
203: column_types += [:string, :text] if [nil, :like, :unlike, :ne, :eq].include?(operator)
204: column_types += [:double, :float, :decimal] if value =~ NUMERICAL_REGXP
205: column_types += [:integer] if value =~ INTEGER_REGXP
206: column_types += [:datetime, :date, :timestamp] if (parse_temporal(value))
207:
208: default_fields.select { |field| column_types.include?(field.type) && !field.set? }
209: end
this method return definitions::field object from string
# File lib/scoped_search/definition.rb, line 175
175: def field_by_name(name)
176: field = fields[name.to_sym] unless name.blank?
177: if field.nil?
178: dotted = name.to_s.split('.')[0]
179: field = fields[dotted.to_sym] unless dotted.nil?
180: end
181: field
182: end
# File lib/scoped_search/definition.rb, line 164
164: def fields
165: @profile ||= :default
166: @profile_fields[@profile] ||= {}
167: end
this method is used by the syntax auto completer to suggest operators.
# File lib/scoped_search/definition.rb, line 185
185: def operator_by_field_name(name)
186: field = field_by_name(name)
187: return [] if field.nil?
188: return field.operators if field.operators
189: return ['= ', '!= '] if field.set?
190: return ['= ', '> ', '< ', '<= ', '>= ','!= ', '^ ', '!^ '] if field.numerical?
191: return ['= ', '!= ', '~ ', '!~ ', '^ ', '!^ '] if field.textual?
192: return ['= ', '> ', '< '] if field.temporal?
193: raise ScopedSearch::QueryNotSupported, "could not verify '#{name}' type, this can be a result of a definition error"
194: 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 214
214: def parse_temporal(value)
215: return Date.current if value =~ /\btoday\b/i
216: return 1.day.ago.to_date if value =~ /\byesterday\b/i
217: return (eval(value.strip.gsub(/\s+/,'.').downcase)).to_datetime if value =~ /\A\s*\d+\s+\bhours?|minutes?\b\s+\bago\b\s*\z/i
218: 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
219: DateTime.parse(value, true) rescue nil
220: end
# File lib/scoped_search/definition.rb, line 169
169: def unique_fields
170: @profile ||= :default
171: @profile_unique_fields[@profile] ||= []
172: end
Registers the complete_for method within the class that is used for searching.
# File lib/scoped_search/definition.rb, line 262
262: def register_complete_for! # :nodoc
263: @klass.class_eval do
264: def self.complete_for(query, options = {})
265: ScopedSearch::AutoCompleteBuilder.auto_complete(@scoped_search , query, options)
266: end
267: end
268: end
Registers the search_for named scope within the class that is used for searching.
# File lib/scoped_search/definition.rb, line 238
238: def register_named_scope! # :nodoc
239: if @klass.ancestors.include?(ActiveRecord::Base)
240: case ActiveRecord::VERSION::MAJOR
241: when 2
242: @klass.named_scope(:search_for, lambda { |*args| ScopedSearch::QueryBuilder.build_query(self, args[0], args[1]) })
243: when 3
244: @klass.scope(:search_for, lambda { |*args|
245: find_options = ScopedSearch::QueryBuilder.build_query(self, args[0], args[1])
246: search_scope = @klass.scoped
247: search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions]
248: search_scope = search_scope.includes(find_options[:include]) if find_options[:include]
249: search_scope = search_scope.joins(find_options[:joins]) if find_options[:joins]
250: search_scope = search_scope.reorder(find_options[:order]) if find_options[:order]
251: search_scope
252: })
253: else
254: raise "This ActiveRecord version is currently not supported!"
255: end
256: else
257: raise "Currently, only ActiveRecord 2.1 or higher is supported!"
258: end
259: end