class GenericSearch::Klass
Attributes
base_class[RW]
Utility attributes
base_table[RW]
Utility attributes
group[RW]
Clause attributes
grouped_results[RW]
Utility attributes
having[RW]
Clause attributes
includes[RW]
Clause attributes
joins[RW]
Clause attributes
limit[RW]
Clause attributes
limit_result_count[RW]
Output attributes
messages[RW]
Output attributes
no_limit_count[RW]
Output attributes
options[RW]
Clause attributes
params[RW]
Utility attributes
response[RW]
Output attributes
results[RW]
Output attributes
select[RW]
Clause attributes
sort_order[RW]
Clause attributes
start[RW]
Clause attributes
status[RW]
Output attributes
where[RW]
Clause attributes
Public Class Methods
new(params, base_class)
click to toggle source
==== Hash Inputs: ===
{
:query => "responsibles(username=ksmanoj)", :results => "scripts(id, name), responsibles", :limit => 5, :options => "no_results"
}
# File lib/generic_search.rb, line 56 def initialize(params, base_class) self.base_class = base_class.is_a?(String) ? base_class.constantize : base_class self.base_table = self.base_class.table_name unless params.is_a?(Hash) or params.is_a?(HashWithIndifferentAccess) raise GenericSearch::UnknownInputType end self.params = params self.validate_syntax return unless self.errors.blank? self.build_where(params[:query]) self.build_results(params[:results]) self.build_group(params[:group]) self.build_having(params[:having]) self.build_options(params[:options]) self.build_limit(params[:limit]) self.build_start(params[:start]) self.build_sort_order(params[:sort_order]) end
Public Instance Methods
search()
click to toggle source
# File lib/generic_search.rb, line 82 def search unless self.errors.blank? self.status = :bad_request self.messages = self.errors.full_messages self.build_response return self.response end table_relation_map = self.base_class._table_relation relation_table_map = self.base_class._relation_table includes = Hash.new json_includes = Hash.new self.select.each do |table, value| table = table.strip relationship_name = table_relation_map[table] relationship_name = table.intern if !relationship_name or relation_table_map[table.intern] includes[relationship_name] = {} if table != self.base_table json_includes[relationship_name] = {:only => self.select[table]} if table != self.base_table end # TODO: Solve n+1 issue for custom columns #config = GenericSearch.config[self.base_table.intern][:for_select] #selected_fields = table_selected_fields[self.base_table] # #config.each do |custom_column, attrs| # if attrs[:include] and selected_fields.include?(custom_column.to_s) # selected_fields << attrs[:include] # end #end self.results = self.base_class.where(self.where).joins(self.joins).includes(self.includes).reorder(self.sort_order) #result_list = @model_class.joins(@joins).includes(includes).where(@where_clause).distinct # TODO: Test required if self.options[:distinct] self.results = self.results.uniq end # ========== Limiting & Grouping ========= # TODO: Test required if self.options[:no_grouped_results] if self.group self.results = self.results.group(self.group) end if self.having self.results = self.results.having(self.having) end else if self.group group_result_counts = self.results.group(self.group).count end end # TODO: If there is a limit then only following count query has to be executed otherwise use .length if self.options[:no_limit_count] # Note: If no limit or start, then .length will fire the query, from that length is calculated. # Additional count query is not required self.no_limit_count = (self.limit || self.start) ? self.results.count : self.results.length #self.no_limit_count = self.results.count end # TODO: Test required unless self.options[:no_results] self.results = self.results.limit(self.limit).offset(self.start) end # ============== Group result processing # TODO: Test required if group_result_counts # Hack to dynamically group the array of objects eval_str = @group_object_access.collect { |i| "result.#{i}.to_s" }.join(' + ') grouped_result = self.results.group_by { |result| eval eval_str } group_hsh = group_result_counts.collect do |values, group_result_count| values = values.is_a?(Array) ? values.collect(&:to_s) : [values.to_s] result_key = values.join('') results = if self.options[:no_results] [] else #grouped_result[result_key].as_json(:include => json_includes, :only => @table_selected_fields[self.base_table]) grouped_result[result_key].as_json(:include => json_includes, :only => self.select[self.base_table], :methods => self.select[self.base_table]) end { :group_by_field => self.group.join(', '), :group_by_value => values.join(','), :num_results => group_result_count, #:results => grouped_result[result_key] :results => results } end else results = if self.options[:no_results] [] else #self.results.as_json(:include => json_includes, :only => @table_selected_fields[self.base_table]) #self.results.as_json(:include => json_includes, :only => self.select[self.base_table], :methods => [:address_ids]) self.results.as_json(:include => json_includes, :only => self.select[self.base_table], :methods => self.select[self.base_table]) end group_hsh = [{:num_results => self.results.length, :results => results}] end self.grouped_results = group_hsh limit_result_count = 0 self.grouped_results.each do |grouped_result| #limit_result_count += grouped_result["results"].count limit_result_count += grouped_result[:num_results] end self.limit_result_count = limit_result_count self.status = :ok self.build_response end