module IsSearchable def self.included(base) base.extend(IncludeClassMethods) end module IncludeClassMethods def is_searchable(options) @query_condition = options[:by_query] @filter_comparisons = options[:and_filters] self.extend ModelClassMethods end module ModelClassMethods def search_count(query, options={}) filters = options[:filters] || {} self.count_by_sql("SELECT COUNT(*) FROM (SELECT #{self.table_name}.* FROM #{self.table_name} #{render_condition_for_query_and_filters(query, filters)} GROUP BY #{self.table_name}.id) as tmpA") end def search(query, options={}) limit = options[:limit] || 10 offset = options[:offset] || 0 filters = options[:filters] || {} puts "SELECT #{self.table_name}.* FROM #{self.table_name} #{render_condition_for_query_and_filters(query, filters)} GROUP BY #{self.table_name}.id LIMIT #{limit} OFFSET #{offset}" self.find_by_sql("SELECT #{self.table_name}.* FROM #{self.table_name} #{render_condition_for_query_and_filters(query, filters)} GROUP BY #{self.table_name}.id LIMIT #{limit} OFFSET #{offset}") end def render_condition_for_query_and_filters(query, filters) #search in: first_name, last_name, identifier "WHERE (#{self.render_query_condition(query)}) AND (#{self.render_filter_condition(filters)})" end def render_query_condition(query) self.replace_named_bind_variables(@query_condition, {:query => query, :like_query => '%' + query.to_s + '%'}) end def render_filter_condition(filters) [1, filters.collect do |key,val| val = "%#{val}%" if @filter_comparisons[key.to_s] =~ /LIKE/ self.replace_bind_variables(@filter_comparisons[key.to_s], [val]) end].flatten.join(' AND ') end end end end