Class: Queries::Query

Inherits:
Object
  • Object
show all
Includes:
Arel::Nodes, Concerns::Identifiers
Defined in:
lib/queries/query.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(string, project_id: nil, **keyword_args) ⇒ Query

Returns a new instance of Query

Parameters:

  • args (Hash)


33
34
35
36
37
38
39
# File 'lib/queries/query.rb', line 33

def initialize(string, project_id: nil, **keyword_args)
  @query_string = string
  # @query_string = '' if !(string =~ /\S/)
  @options = keyword_args
  @project_id = project_id
  build_terms
end

Instance Attribute Details

#dynamic_limitInteger

Returns:

  • (Integer)


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

def dynamic_limit
  @dynamic_limit
end

#optionsObject

parameters from keyword_args, used to group and pass along things like annotator params



27
28
29
# File 'lib/queries/query.rb', line 27

def options
  @options
end

#project_idObject

Returns the value of attribute project_id



24
25
26
# File 'lib/queries/query.rb', line 24

def project_id
  @project_id
end

#query_stringObject

Returns the value of attribute query_string



22
23
24
# File 'lib/queries/query.rb', line 22

def query_string
  @query_string
end

#termsArray

Returns:

  • (Array)


61
62
63
# File 'lib/queries/query.rb', line 61

def terms
  @terms
end

Instance Method Details

#alphabetic_stringsArray

Returns:

  • (Array)


88
89
90
# File 'lib/queries/query.rb', line 88

def alphabetic_strings
  Utilities::Strings.alphabetic_strings(query_string)
end

#autocompleteArray

Returns default the autocomplete result to all

Returns:

  • (Array)

    default the autocomplete result to all



313
314
315
# File 'lib/queries/query.rb', line 313

def autocomplete
  all.to_a
end

#autocomplete_cachedActiveRecord::Relation

Returns:

  • (ActiveRecord::Relation)


336
337
338
339
340
# File 'lib/queries/query.rb', line 336

def autocomplete_cached
  a = cached
  return nil if a.nil?
  base_query.where(a.to_sql).limit(20)
end

#autocomplete_cached_wildcard_anywhereActiveRecord::Relation

Returns removes years/integers!

Returns:

  • (ActiveRecord::Relation)

    removes years/integers!



329
330
331
332
333
# File 'lib/queries/query.rb', line 329

def autocomplete_cached_wildcard_anywhere
  a = match_wildcard_in_cached
  return nil if a.nil?
  base_query.where(a.to_sql).limit(20)
end

#autocomplete_exact_idActiveRecord::Relation

Returns:

  • (ActiveRecord::Relation)


318
319
320
# File 'lib/queries/query.rb', line 318

def autocomplete_exact_id
  base_query.where(id: query_string).limit(1)
end

#autocomplete_exactly_namedActiveRecord::Relation

Returns:

  • (ActiveRecord::Relation)


349
350
351
352
# File 'lib/queries/query.rb', line 349

def autocomplete_exactly_named
  return nil if query_string.blank?
  base_query.where(exactly_named.to_sql).limit(20)
end

#autocomplete_namedActiveRecord::Relation

Returns:

  • (ActiveRecord::Relation)


355
356
357
358
# File 'lib/queries/query.rb', line 355

def autocomplete_named
  return nil if query_string.blank?
  base_query.where(named.to_sql).limit(5)
end

#autocomplete_ordered_wildcard_pieces_in_cachedActiveRecord::Relation

Returns:

  • (ActiveRecord::Relation)


323
324
325
# File 'lib/queries/query.rb', line 323

def autocomplete_ordered_wildcard_pieces_in_cached
  base_query.where(match_ordered_wildcard_pieces_in_cached.to_sql).limit(5)
end

#autocomplete_start_dateObject



342
343
344
345
346
# File 'lib/queries/query.rb', line 342

def autocomplete_start_date
  a = with_start_date 
  return nil if a.nil?
  base_query.where(a.to_sql).limit(20)
end

#build_termsArray

Ultimately we should replace this concept with full text indexing.

Returns:

  • (Array)

    a reasonable (starting) interpretation of any query string



68
69
70
# File 'lib/queries/query.rb', line 68

def build_terms
  @terms = @query_string.blank? ? [] : [end_wildcard, start_and_end_wildcard]
end

#cachedActiveRecord::Relation?

TODO: rename :cached_matches or similar

Returns:

  • (ActiveRecord::Relation, nil)

    cached matches full query string wildcarded



259
260
261
262
263
264
265
# File 'lib/queries/query.rb', line 259

def cached
  if !terms.empty?
    table[:cached].matches_any(terms)
  else
    nil
  end
end

#combine_or_clauses(clauses) ⇒ Arel::Nodes::Grouping

Returns:

  • (Arel::Nodes::Grouping)

Raises:

  • (TaxonWorks::Error)


297
298
299
300
301
302
303
304
305
# File 'lib/queries/query.rb', line 297

def combine_or_clauses(clauses)
  clauses.compact!
  raise TaxonWorks::Error, 'combine_or_clauses called without a clause, ensure at least one exists' unless !clauses.empty?
  a = clauses.shift
  clauses.each do |b|
    a = a.or(b)
  end
  a
end

#end_wildcardString

Returns:

  • (String)


78
79
80
# File 'lib/queries/query.rb', line 78

def end_wildcard
  query_string + '%'
end

#exactly_namedArel::Nodes::Matches

Returns:

  • (Arel::Nodes::Matches)


237
238
239
# File 'lib/queries/query.rb', line 237

def exactly_named
  table[:name].eq(query_string) if !query_string.blank?
end

#fragmentsArray

Used in unordered AND searches

Returns:

  • (Array)

    if 1-5 alphabetic_strings, those alphabetic_strings wrapped in wildcards, else none.



121
122
123
124
125
126
127
128
# File 'lib/queries/query.rb', line 121

def fragments
  a = alphabetic_strings
  if a.size > 0 && a.size < 6
    a.collect{|a| "%#{a}%"}
  else
    []
  end
end

#integersArray

Returns of strings representing integers

Returns:

  • (Array)

    of strings representing integers



107
108
109
110
# File 'lib/queries/query.rb', line 107

def integers
  return [] if query_string.blank?
  query_string.split(/\s+/).select{|t| Utilities::Strings.is_i?(t)}
end

#match_ordered_wildcard_pieces_in_cachedArel::Nodes::Matches

Returns:

  • (Arel::Nodes::Matches)


278
279
280
# File 'lib/queries/query.rb', line 278

def match_ordered_wildcard_pieces_in_cached
  table[:cached].matches(wildcard_pieces)
end

#match_wildcard_end_in_cachedArel::Nodes::Matches

match ALL wildcards, but unordered, if 2 - 6 pieces provided

Returns:

  • (Arel::Nodes::Matches)


284
285
286
# File 'lib/queries/query.rb', line 284

def match_wildcard_end_in_cached
  table[:cached].matches(end_wildcard)
end

#match_wildcard_in_cachedArel::Nodes::Matches

match ALL wildcards, but unordered, if 2 - 6 pieces provided

Returns:

  • (Arel::Nodes::Matches)


290
291
292
293
294
# File 'lib/queries/query.rb', line 290

def match_wildcard_in_cached
  b = fragments
  return nil if b.empty?
  table[:cached].matches_all(b)
end

#namedArel::Nodes::Matches

Returns:

  • (Arel::Nodes::Matches)


232
233
234
# File 'lib/queries/query.rb', line 232

def named
  table[:name].matches_any(terms) if terms.any?
end

#no_digitsString

Returns:

  • (String)


153
154
155
# File 'lib/queries/query.rb', line 153

def no_digits
  query_string.gsub(/\d/, '').strip
end

#only_idsQuery?

Returns used in or_clauses, match on id only if integers alone provided.

Returns:

  • (Query, nil)

    used in or_clauses, match on id only if integers alone provided.



197
198
199
200
201
202
203
# File 'lib/queries/query.rb', line 197

def only_ids
  if only_integers?
    with_id
  else
    nil
  end
end

#only_integers?Boolean

Returns true if the query string only contains integers

Returns:

  • (Boolean)

    true if the query string only contains integers



114
115
116
# File 'lib/queries/query.rb', line 114

def only_integers?
  !(query_string =~ /[^\d\s]/i) && !integers.empty?
end

#parentArel::Nodes::TableAlias

Returns:

  • (Arel::Nodes::TableAlias)


242
243
244
# File 'lib/queries/query.rb', line 242

def parent
  table.alias
end

#parent_child_joinScope

Returns:

  • (Scope)


173
174
175
# File 'lib/queries/query.rb', line 173

def parent_child_join
  table.join(parent).on(table[:parent_id].eq(parent[:id])).join_sources # !! join_sources ftw
end

#parent_child_whereArel::Nodes::Grouping

Match at two levels, for example, 'wa te“ will match ”Washington Co., Texas“

Returns:

  • (Arel::Nodes::Grouping)


179
180
181
182
183
# File 'lib/queries/query.rb', line 179

def parent_child_where
  a,b = query_string.split(/\s+/, 2)
  return table[:id].eq(-1) if a.nil? || b.nil?
  table[:name].matches("#{a}%").and(parent[:name].matches("#{b}%"))
end

#piecesArray

Returns split on whitespace

Returns:

  • (Array)

    split on whitespace



132
133
134
# File 'lib/queries/query.rb', line 132

def pieces
  query_string.split(/\s+/)
end

#resultArray

Returns the results of the query as ActiveRecord objects

Returns:

  • (Array)

    the results of the query as ActiveRecord objects



43
44
45
# File 'lib/queries/query.rb', line 43

def result
  []
end

#scopeScope

stub

Returns:

  • (Scope)


49
50
51
# File 'lib/queries/query.rb', line 49

def scope
  where('1 = 2')
end

#simple_dateDate.new?

Returns:

  • (Date.new, nil)


206
207
208
209
210
211
212
# File 'lib/queries/query.rb', line 206

def simple_date
  begin
    Date.parse(query_string)
  rescue ArgumentError
    return nil
  end
end

#start_and_end_wildcardString

Returns:

  • (String)


83
84
85
# File 'lib/queries/query.rb', line 83

def start_and_end_wildcard
  '%' + query_string + '%'
end

#start_wildcardString

Returns:

  • (String)


73
74
75
# File 'lib/queries/query.rb', line 73

def start_wildcard
  '%' + query_string
end

#wildcard_piecesString

Returns if `foo, and 123 and stuff` then %foo%and%123%and%stuff%

Returns:

  • (String)

    if `foo, and 123 and stuff` then %foo%and%123%and%stuff%



148
149
150
# File 'lib/queries/query.rb', line 148

def wildcard_pieces
  '%' + query_string.gsub(/[\s\W]+/, '%') + '%'
end

#wildcard_wrapped_integersArray

Returns:

  • (Array)


137
138
139
# File 'lib/queries/query.rb', line 137

def wildcard_wrapped_integers
  integers.collect{|i| "%#{i}%"}
end

#wildcard_wrapped_yearsArray

Returns:

  • (Array)


142
143
144
# File 'lib/queries/query.rb', line 142

def wildcard_wrapped_years
  years.collect{|i| "%#{i}%"}
end

#with_cachedArel::Nodes::Matches

Returns:

  • (Arel::Nodes::Matches)


268
269
270
# File 'lib/queries/query.rb', line 268

def with_cached
  table[:cached].eq(query_string)
end

#with_cached_likeArel::Nodes::Matches

Returns:

  • (Arel::Nodes::Matches)


273
274
275
# File 'lib/queries/query.rb', line 273

def with_cached_like
  table[:cached].matches(start_and_end_wildcard)
end

#with_idQuery?

Returns used in or_clauses

Returns:

  • (Query, nil)

    used in or_clauses



187
188
189
190
191
192
193
# File 'lib/queries/query.rb', line 187

def with_id
  if integers.any?
    table[:id].eq_any(integers)
  else
    nil
  end
end

#with_project_idArel::Nodes::Equality

TODO: nil/or clause this

Returns:

  • (Arel::Nodes::Equality)


248
249
250
251
252
253
254
# File 'lib/queries/query.rb', line 248

def with_project_id
  if project_id
    table[:project_id].eq(project_id)
  else
    nil
  end
end

#with_start_dateObject



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/queries/query.rb', line 214

def with_start_date
  if d = simple_date
    r = []
    r.push(table[:start_date_day].eq(d.day)) if d.day
    r.push(table[:start_date_month].eq(d.month)) if d.month
    r.push(table[:start_date_year].eq(d.year)) if d.year

    q = r.pop
    r.each do |z|
      q = q.and(z)
    end
    q
  else
    nil
  end
end

#year_letterString?

Returns the first letter recognized as coming directly past the first year

`Smith, 1920a. ... ` returns `a`

Returns:

  • (String, nil)

    the first letter recognized as coming directly past the first year

    `Smith, 1920a. ... ` returns `a`


101
102
103
# File 'lib/queries/query.rb', line 101

def year_letter
  query_string.match(/\d{4}([a-zAZ]+)/).to_a.last
end

#yearsArray

Returns those strings that represent years

Returns:

  • (Array)

    those strings that represent years



94
95
96
# File 'lib/queries/query.rb', line 94

def years
  query_string.scan(/\d{4}/).to_a.uniq
end