lib/scoped_search/definition.rb in scoped_search-4.0.0 vs lib/scoped_search/definition.rb in scoped_search-4.1.0

- old
+ new

@@ -79,15 +79,14 @@ @relation = relation @validator = validator @word_size = word_size # Store this field in the field array - definition.fields[rename ? rename.to_sym : @field] ||= self - definition.unique_fields << self + definition.define_field(rename || @field, self) # Store definition for aliases as well - aliases.each { |al| definition.fields[al.to_sym] ||= self } + aliases.each { |al| definition.define_field(al, self) } end # The ActiveRecord-based class that belongs to this field. def klass @klass ||= if relation @@ -191,18 +190,33 @@ register_complete_for! unless klass.respond_to?(:complete_for) end attr_accessor :profile, :default_order + def super_definition + klass.superclass.try(:scoped_search_definition) + end + + def define_field(name, field) + @profile ||= :default + @profile_fields[@profile] ||= {} + @profile_fields[@profile][name.to_sym] ||= field + @profile_unique_fields[@profile] ||= [] + @profile_unique_fields[@profile] = (@profile_unique_fields[@profile] + [field]).uniq + field + end + def fields @profile ||= :default @profile_fields[@profile] ||= {} + super_definition ? super_definition.fields.merge(@profile_fields[@profile]) : @profile_fields[@profile] end def unique_fields @profile ||= :default @profile_unique_fields[@profile] ||= [] + super_definition ? (super_definition.unique_fields + @profile_unique_fields[@profile]).uniq : @profile_unique_fields[@profile] end # this method return definitions::field object from string def field_by_name(name) field = fields[name.to_sym] unless name.blank? @@ -239,17 +253,20 @@ default_fields.select { |field| column_types.include?(field.type) && !field.set? } 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' + # Supported formats are Today, Yesterday, Sunday, '1 day ago', '2 hours ago', '3 months ago', '4 weeks from now', 'Jan 23, 2004' # And many more formats that are documented in Ruby DateTime API Doc. def parse_temporal(value) return Date.current if value =~ /\btoday\b/i return 1.day.ago.to_date if value =~ /\byesterday\b/i + return 1.day.from_now.to_date if value =~ /\btomorrow\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 + return (eval($1.strip.gsub(/from\s+now/i,'from_now').gsub(/\s+/,'.').downcase)).to_datetime if value =~ /\A\s*(\d+\s+\b(?:hours?|minutes?)\b\s+\bfrom\s+now)\b\s*\z/i + return (eval($1.strip.gsub(/from\s+now/i,'from_now').gsub(/\s+/,'.').downcase)).to_date if value =~ /\A\s*(\d+\s+\b(?:days?|weeks?|months?|years?)\b\s+\bfrom\s+now)\b\s*\z/i DateTime.parse(value, true) rescue nil end # Returns a list of fields that should be searched on by default. # @@ -272,23 +289,24 @@ protected # Registers the search_for named scope within the class that is used for searching. def register_named_scope! # :nodoc - definition = self - @klass.scope(:search_for, proc { |query, options| - klass = definition.klass + @klass.define_singleton_method(:search_for) do |query = '', options = {}| + # klass may be different to @klass if the scope is called on a subclass + klass = self + definition = klass.scoped_search_definition search_scope = klass.all - find_options = ScopedSearch::QueryBuilder.build_query(definition, query || '', options || {}) + 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] search_scope - }) + end end # Registers the complete_for method within the class that is used for searching. def register_complete_for! # :nodoc @klass.extend(ScopedSearch::AutoCompleteClassMethods)