lib/scoped_search.rb in wvanbergen-scoped_search-0.7.3 vs lib/scoped_search.rb in wvanbergen-scoped_search-1.0.0
- old
+ new
@@ -1,75 +1,102 @@
module ScopedSearch
module ClassMethods
-
- def self.extended(base)
+
+ def self.extended(base) # :nodoc:
require 'scoped_search/reg_tokens'
require 'scoped_search/query_language_parser'
require 'scoped_search/query_conditions_builder'
end
- # Creates a named scope in the class it was called upon
+ # Creates a named scope in the class it was called upon.
+ #
+ # fields:: The fields to search on.
def searchable_on(*fields)
# Make sure that the table to be searched actually exists
if self.table_exists?
+
+ # Get a collection of fields to be searched on.
if fields.first.class.to_s == 'Hash'
if fields.first.has_key?(:only)
+ # only search on these fields.
fields = fields.first[:only]
elsif fields.first.has_key?(:except)
- fields = self.column_names.collect { |column|
- fields.first[:except].include?(column.to_sym) ? nil : column.to_sym }.compact
+ # Get all the fields and remove any that are in the -except- list.
+ fields = self.column_names.collect { |column| fields.first[:except].include?(column.to_sym) ? nil : column.to_sym }.compact
end
end
- assoc_models = self.reflections.collect { |m| m[0] }
+ # Get an array of associate modules.
+ assoc_models = self.reflections.collect { |key,value| key }
+
+ # Subtract out the fields to be searched on that are part of *this* model.
+ # Any thing left will be associate module fields to be searched on.
assoc_fields = fields - self.column_names.collect { |column| column.to_sym }
+
+ # Subtraced out the associated fields from the fields so that you are only left
+ # with fields in *this* model.
fields -= assoc_fields
+ # Loop through each of the associate models and group accordingly each
+ # associate model field to search. Assuming the following relations:
+ # has_many :clients
+ # has_many :notes,
+ # belongs_to :user_type
+ # assoc_groupings will look like
+ # assoc_groupings = {:clients => [:first_name, :last_name],
+ # :notes => [:descr],
+ # :user_type => [:identifier]}
assoc_groupings = {}
assoc_models.each do |assoc_model|
assoc_groupings[assoc_model] = []
assoc_fields.each do |assoc_field|
unless assoc_field.to_s.match(/^#{assoc_model.to_s}_/).nil?
assoc_groupings[assoc_model] << assoc_field.to_s.sub(/^#{assoc_model.to_s}_/, '').to_sym
end
end
end
-
+
+ # If a grouping does not contain any fields to be searched on then remove it.
assoc_groupings = assoc_groupings.delete_if {|group, field_group| field_group.empty?}
+ # Set the appropriate class attributes.
self.cattr_accessor :scoped_search_fields, :scoped_search_assoc_groupings
self.scoped_search_fields = fields
self.scoped_search_assoc_groupings = assoc_groupings
self.named_scope :search_for, lambda { |keywords| self.build_scoped_search_conditions(keywords) }
end
end
# Build a hash that is used for the named_scope search_for.
# This function will split the search_string into keywords, and search for all the keywords
- # in the fields that were provided to searchable_on
+ # in the fields that were provided to searchable_on.
+ #
+ # search_string:: The search string to parse.
def build_scoped_search_conditions(search_string)
if search_string.nil? || search_string.strip.blank?
return {:conditions => nil}
else
query_fields = {}
self.scoped_search_fields.each do |field|
field_name = connection.quote_table_name(table_name) + "." + connection.quote_column_name(field)
query_fields[field_name] = self.columns_hash[field.to_s].type
end
+ assoc_model_indx = 0
+ assoc_fields_indx = 1
assoc_models_to_include = []
- self.scoped_search_assoc_groupings.each do |group|
- assoc_models_to_include << group[0]
- group[1].each do |group_field|
- field_name = connection.quote_table_name(group[0].to_s.pluralize) + "." + connection.quote_column_name(group_field)
- query_fields[field_name] = self.reflections[group[0]].klass.columns_hash[group_field.to_s].type
+ self.scoped_search_assoc_groupings.each do |group|
+ assoc_models_to_include << group[assoc_model_indx]
+ group[assoc_fields_indx].each do |group_field|
+ field_name = connection.quote_table_name(group[assoc_model_indx].to_s.pluralize) + "." + connection.quote_column_name(group_field)
+ query_fields[field_name] = self.reflections[group[assoc_model_indx]].klass.columns_hash[group_field.to_s].type
end
end
search_conditions = QueryLanguageParser.parse(search_string)
conditions = QueryConditionsBuilder.build_query(search_conditions, query_fields)
-
+
retVal = {:conditions => conditions}
retVal[:include] = assoc_models_to_include unless assoc_models_to_include.empty?
return retVal
end
\ No newline at end of file