Class: GenericSearch::Klass

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Validations, BuildMethods, Validation
Defined in:
lib/generic_search.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from BuildMethods

#build_group, #build_having, #build_limit, #build_options, #build_response, #build_results, #build_sort_order, #build_start, #build_where

Methods included from Validation

#valid_syntax?, #validate, #validate_columns, #validate_group, #validate_limit, #validate_query, #validate_results, #validate_sort_order, #validate_syntax, #validate_table_columns, #validate_uri_syntax

Constructor Details

#initialize(params, base_class) ⇒ Klass

Hash Inputs: ===

:query => "responsibles(username=ksmanoj)",
:results => "scripts(id, name), responsibles",
:limit => 5,
:options => "no_results"



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 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

Instance Attribute Details

#base_classObject

Utility attributes



33
34
35
# File 'lib/generic_search.rb', line 33

def base_class
  @base_class
end

#base_tableObject

Utility attributes



33
34
35
# File 'lib/generic_search.rb', line 33

def base_table
  @base_table
end

#groupObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def group
  @group
end

#grouped_resultsObject

Utility attributes



33
34
35
# File 'lib/generic_search.rb', line 33

def grouped_results
  @grouped_results
end

#havingObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def having
  @having
end

#includesObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def includes
  @includes
end

#joinsObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def joins
  @joins
end

#limitObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def limit
  @limit
end

#limit_result_countObject

Output attributes



36
37
38
# File 'lib/generic_search.rb', line 36

def limit_result_count
  @limit_result_count
end

#messagesObject

Output attributes



36
37
38
# File 'lib/generic_search.rb', line 36

def messages
  @messages
end

#no_limit_countObject

Output attributes



36
37
38
# File 'lib/generic_search.rb', line 36

def no_limit_count
  @no_limit_count
end

#optionsObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def options
  @options
end

#paramsObject

Utility attributes



33
34
35
# File 'lib/generic_search.rb', line 33

def params
  @params
end

#responseObject

Output attributes



36
37
38
# File 'lib/generic_search.rb', line 36

def response
  @response
end

#resultsObject

Output attributes



36
37
38
# File 'lib/generic_search.rb', line 36

def results
  @results
end

#selectObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def select
  @select
end

#sort_orderObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def sort_order
  @sort_order
end

#startObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def start
  @start
end

#statusObject

Output attributes



36
37
38
# File 'lib/generic_search.rb', line 36

def status
  @status
end

#whereObject

Clause attributes



30
31
32
# File 'lib/generic_search.rb', line 30

def where
  @where
end

Instance Method Details

#searchObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# 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