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)