Class: Queries::TaxonName::Autocomplete

Inherits:
Query::Autocomplete show all
Defined in:
lib/queries/taxon_name/autocomplete.rb

Instance Attribute Summary collapse

Attributes inherited from Query::Autocomplete

#dynamic_limit, #project_id, #query_string

Attributes inherited from Query

#query_string, #terms

Instance Method Summary collapse

Methods inherited from Query::Autocomplete

#autocomplete_cached, #autocomplete_cached_wildcard_anywhere, #autocomplete_common_name_exact, #autocomplete_common_name_like, #autocomplete_exact_id, #autocomplete_exactly_named, #autocomplete_named, #autocomplete_ordered_wildcard_pieces_in_cached, #combine_or_clauses, #common_name_name, #common_name_table, #common_name_wild_pieces, #exactly_named, #fragments, #integers, #match_wildcard_end_in_cached, #match_wildcard_in_cached, #named, #only_ids, #only_integers?, #parent, #parent_child_join, #parent_child_where, #pieces, #scope, #string_fragments, #wildcard_wrapped_integers, #wildcard_wrapped_years, #with_cached, #with_cached_like, #with_id, #with_project_id, #year_letter, #years

Methods inherited from Query

#alphabetic_strings, #alphanumeric_strings, base_name, #base_name, #build_terms, #cached_facet, #end_wildcard, #levenshtein_distance, #match_ordered_wildcard_pieces_in_cached, #no_terms?, #referenced_klass, referenced_klass, #referenced_klass_except, #referenced_klass_union, #start_and_end_wildcard, #start_wildcard, #table, #wildcard_pieces

Constructor Details

#initialize(string, project_id: nil, valid: nil, exact: nil, no_leaves: nil, nomenclature_group: [], type: [], parent_id: []) ⇒ Autocomplete

Returns a new instance of Autocomplete.

Parameters:

  • args (Hash)


37
38
39
40
41
42
43
44
45
# File 'lib/queries/taxon_name/autocomplete.rb', line 37

def initialize(string, project_id: nil, valid: nil, exact: nil, no_leaves: nil, nomenclature_group: [], type: [], parent_id: [])
  @nomenclature_group = nomenclature_group
  @valid = valid == 'true' ? true : (valid == 'false' ? false : nil)
  @type = type
  @parent_id = parent_id
  @no_leaves = no_leaves == 'true' ? true : (no_leaves == 'false' ? false : nil)
  @exact = (exact == 'true' ? true : (exact == 'false' ? false : nil))
  super
end

Instance Attribute Details

#exactBoolean

Returns &exact=<“true”|“false”> if 'true' then only #name = query_string results are returned (no fuzzy matching).

Returns:

  • (Boolean)

    &exact=<“true”|“false”> if 'true' then only #name = query_string results are returned (no fuzzy matching)



29
30
31
# File 'lib/queries/taxon_name/autocomplete.rb', line 29

def exact
  @exact
end

#no_leavesBoolean

Returns &no_leaves=<“true”|“false”> if 'true' then only names with descendents will be returned.

Returns:

  • (Boolean)

    &no_leaves=<“true”|“false”> if 'true' then only names with descendents will be returned



34
35
36
# File 'lib/queries/taxon_name/autocomplete.rb', line 34

def no_leaves
  @no_leaves
end

#nomenclature_groupArray

and_clause

Returns:

  • (Array)


8
9
10
# File 'lib/queries/taxon_name/autocomplete.rb', line 8

def nomenclature_group
  @nomenclature_group
end

#parent_idArray

Returns &parent_id[]=&parent_id=<other_int> etc.

Returns:



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

def parent_id
  @parent_id
end

#typeArray

Returns &type[]=<Protonym, Combination, Hybrid, etc.>&type[]=<other type> etc.

Returns:

  • (Array)

    &type[]=<Protonym, Combination, Hybrid, etc.>&type[]=<other type> etc.



20
21
22
# File 'lib/queries/taxon_name/autocomplete.rb', line 20

def type
  @type
end

#validBoolean?

Returns &valid=<“true”|“false”>

if 'true'  then id == cached_valid_taxon_name_id
if 'false' then id != cached_valid_taxon_name
if nil   then no check made, i.e. all names

string is converted to Boolean here.

Returns:

  • (Boolean, nil)

    &valid=<“true”|“false”>

    if 'true'  then id == cached_valid_taxon_name_id
    if 'false' then id != cached_valid_taxon_name
    if nil   then no check made, i.e. all names
    

    string is converted to Boolean here



16
17
18
# File 'lib/queries/taxon_name/autocomplete.rb', line 16

def valid
  @valid
end

Instance Method Details

#allScope

!! TODO: should be autocomplete and array …

Returns:

  • (Scope)


139
140
141
142
143
144
145
# File 'lib/queries/taxon_name/autocomplete.rb', line 139

def all
  ::TaxonName.select('taxon_names.*, char_length(taxon_names.cached)').
    includes(:ancestor_hierarchies).
    where(where_sql).
    references(:taxon_name_hierarchies).
    limit(dynamic_limit).order('char_length(taxon_names.cached), taxon_names.cached').distinct.all
end

#and_clausesArel:Nodes?

Returns:

  • (Arel:Nodes, nil)


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/queries/taxon_name/autocomplete.rb', line 69

def and_clauses
  clauses = [
    valid_state,
    is_type,
    with_parent_id,
    with_nomenclature_group,
  ].compact

  return nil if clauses.nil?

  a = clauses.shift
  clauses.each do |b|
    a = a.and(b)
  end
  a
end

#authorshipString

Returns:

  • (String)


368
369
370
# File 'lib/queries/taxon_name/autocomplete.rb', line 368

def authorship
  ::Biodiversity::Parser.parse(query_string).dig(:authorship, :normalized)
end

#autocompleteArray

Returns:

  • (Array)


311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/queries/taxon_name/autocomplete.rb', line 311

def autocomplete
  queries = (exact ? exact_autocomplete : comprehensive_autocomplete)
  queries.compact!

  result = []

  queries.each_with_index do |q,i|
    a = q
    a = q.where(project_id: project_id) if project_id.present?
    a = a.where(and_clauses.to_sql) if and_clauses # TODO: duplicates clauses like exact!!
    if !parent_id.empty?
      a = a.descendants_of(::TaxonName.where(id: parent_id))
    end
    a = a.not_leaves if no_leaves
    result += a.to_a
    break if result.count > 19
  end

  result.uniq!
  result[0..19]
end

#autocomplete_cached_author_yearScope

Returns:

  • (Scope)


243
244
245
246
# File 'lib/queries/taxon_name/autocomplete.rb', line 243

def autocomplete_cached_author_year
  a = table[:cached_author_year].matches("#{query_string.gsub(/[,\s]/, '%')}")
  base_query.where(a.to_sql).order('cached ASC').limit(20)
end

#autocomplete_cached_end_wildcardScope

Returns:

  • (Scope)


191
192
193
194
195
# File 'lib/queries/taxon_name/autocomplete.rb', line 191

def autocomplete_cached_end_wildcard
  s = query_string.delete('\\')
  a = table[:cached].matches("#{s}%")
  base_query.where(a.to_sql).limit(20)
end

#autocomplete_cached_name_end_wildcardScope

Returns:

  • (Scope)


220
221
222
223
# File 'lib/queries/taxon_name/autocomplete.rb', line 220

def autocomplete_cached_name_end_wildcard
  a = table[:name].matches("#{query_string}%")
  base_query.where(a.to_sql).limit(20)
end

#autocomplete_cached_wildcard_whitespaceScope

Returns:

  • (Scope)


226
227
228
229
# File 'lib/queries/taxon_name/autocomplete.rb', line 226

def autocomplete_cached_wildcard_whitespace
  a = table[:cached].matches("#{query_string.gsub('. ', ' ').gsub(' ', '%')}")
  base_query.where(a.to_sql).limit(20)
end

#autocomplete_exact_cachedScope

Returns:

  • (Scope)


148
149
150
151
# File 'lib/queries/taxon_name/autocomplete.rb', line 148

def autocomplete_exact_cached
  a = table[:cached].eq(query_string)
  base_query.where(a.to_sql).order('cached_author_year ASC').limit(20)
end

#autocomplete_exact_cached_original_combinationScope

Returns:

  • (Scope)


154
155
156
157
# File 'lib/queries/taxon_name/autocomplete.rb', line 154

def autocomplete_exact_cached_original_combination
  a = table[:cached_original_combination].eq(query_string)
  base_query.where(a.to_sql).order('cached_author_year ASC').limit(20)
end

#autocomplete_exact_name_and_yearScope

Returns:

  • (Scope)


166
167
168
169
170
171
172
173
174
175
# File 'lib/queries/taxon_name/autocomplete.rb', line 166

def autocomplete_exact_name_and_year
  a = alphabetic_strings.select { |b| !(b =~ /\d/) }
  b = years
  if a.size == 1 && !b.empty?
    a = table[:name].eq(a.first).and(table[:cached_author_year].matches_any(wildcard_wrapped_years))
    base_query.where(a.to_sql).limit(10)
  else
    nil
  end
end

#autocomplete_genus_species1(result) ⇒ Scope

Parameters:

  • result (String)

Returns:

  • (Scope)


205
206
207
208
209
# File 'lib/queries/taxon_name/autocomplete.rb', line 205

def autocomplete_genus_species1(result)
  return nil if result.nil?
  a = table[:cached].matches(result)
  base_query.where(a.to_sql).order('type DESC, cached ASC').limit(8)
end

#autocomplete_genus_species2(result) ⇒ Scope

Parameters:

  • result (String)

Returns:

  • (Scope)


213
214
215
216
217
# File 'lib/queries/taxon_name/autocomplete.rb', line 213

def autocomplete_genus_species2(result)
  return nil if result.nil?
  a = table[:cached].matches(result + '%')
  base_query.where(a.to_sql).order('type DESC, cached ASC').limit(8)
end

#autocomplete_name_author_year_fragmentScope?

Returns:

  • (Scope, nil)


232
233
234
235
236
237
238
239
240
# File 'lib/queries/taxon_name/autocomplete.rb', line 232

def autocomplete_name_author_year_fragment
  f = fragments
  if f.size == 2
    a = table[:name].matches(f[0]).and(table[:cached_author_year].matches(f[1]))
    base_query.where(a.to_sql).limit(20)
  else
    nil
  end
end

#autocomplete_taxon_name_author_year_matchesArel::Nodes::Matches

Returns:

  • (Arel::Nodes::Matches)


263
264
265
266
267
# File 'lib/queries/taxon_name/autocomplete.rb', line 263

def autocomplete_taxon_name_author_year_matches
  a = authorship
  return nil if a.nil?
  base_query.where(table[:cached_author_year].matches(a).to_sql).limit(10)
end

#autocomplete_top_cachedScope

Returns:

  • (Scope)


184
185
186
187
188
# File 'lib/queries/taxon_name/autocomplete.rb', line 184

def autocomplete_top_cached
  s = query_string.delete('\\')
  a = table[:cached].matches("#{s}%")
  base_query.where(a.to_sql).limit(1)
end

#autocomplete_top_cached_subgenusScope

Returns:

  • (Scope)


198
199
200
201
# File 'lib/queries/taxon_name/autocomplete.rb', line 198

def autocomplete_top_cached_subgenus
  a = table[:cached].matches("%(#{query_string})")
  base_query.where(a.to_sql).limit(1)
end

#autocomplete_top_nameScope

Returns:

  • (Scope)


178
179
180
181
# File 'lib/queries/taxon_name/autocomplete.rb', line 178

def autocomplete_top_name
  a = table[:name].eq(query_string)
  base_query.where(a.to_sql).order('cached_author_year ASC').limit(20)
end

#autocomplete_wildcard_author_year_joined_piecesScope?

Returns:

  • (Scope, nil)


249
250
251
252
253
# File 'lib/queries/taxon_name/autocomplete.rb', line 249

def autocomplete_wildcard_author_year_joined_pieces
  return nil if pieces.empty?
  a = table[:cached_author_year].matches("%#{pieces.join('%')}%")
  base_query.where(a.to_sql).order('cached ASC').limit(20)
end

#autocomplete_wildcard_cached_original_combinationScope

Returns:

  • (Scope)


160
161
162
163
# File 'lib/queries/taxon_name/autocomplete.rb', line 160

def autocomplete_wildcard_cached_original_combination
  a = table[:cached_original_combination].matches(wildcard_pieces)
  base_query.where(a.to_sql).order('cached_author_year ASC').limit(20)
end

#autocomplete_wildcard_joined_stringsScope?

Returns:

  • (Scope, nil)


256
257
258
259
260
# File 'lib/queries/taxon_name/autocomplete.rb', line 256

def autocomplete_wildcard_joined_strings
  return nil if alphabetic_strings.empty?
  a = table[:cached].matches("%#{alphabetic_strings.join('%')}%")
  base_query.where(a.to_sql).limit(10)
end

#base_queryScope

Returns:

  • (Scope)


351
352
353
354
355
# File 'lib/queries/taxon_name/autocomplete.rb', line 351

def base_query
  ::TaxonName.select('taxon_names.*, char_length(taxon_names.cached)').
    includes(:ancestor_hierarchies).
    order(Arel.sql('char_length(taxon_names.cached), taxon_names.cached ASC')) # TODO: add index to CHAR_LENGTH ?
end

#comprehensive_autocompleteObject



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/queries/taxon_name/autocomplete.rb', line 282

def comprehensive_autocomplete
  z = genus_species

  queries = [
    autocomplete_exact_id,
    autocomplete_exact_cached,
    autocomplete_exact_cached_original_combination,
    autocomplete_identifier_cached_exact,
    autocomplete_exact_name_and_year,
    autocomplete_identifier_identifier_exact,
    autocomplete_top_name,
    autocomplete_top_cached,
    autocomplete_top_cached_subgenus,         # not tested
    autocomplete_genus_species1(z),           # not tested
    autocomplete_genus_species2(z),           # not tested
    autocomplete_cached_end_wildcard,
    # autocomplete_identifier_cached_like, # this query take much longer to complete than any other
    autocomplete_cached_name_end_wildcard,
    autocomplete_cached_wildcard_whitespace,
    autocomplete_name_author_year_fragment,
    autocomplete_taxon_name_author_year_matches,
    autocomplete_cached_author_year,
    autocomplete_wildcard_joined_strings,
    autocomplete_wildcard_author_year_joined_pieces,
    autocomplete_wildcard_cached_original_combination
  ]
end

#exact_autocompleteObject

Used in new taxon name, for example



270
271
272
273
274
275
276
277
278
279
280
# File 'lib/queries/taxon_name/autocomplete.rb', line 270

def exact_autocomplete
  [
    autocomplete_exact_id,
    autocomplete_exact_cached,
    autocomplete_exact_cached_original_combination,
    autocomplete_exact_name_and_year,
    autocomplete_top_name,
    autocomplete_top_cached,
    autocomplete_cached_end_wildcard
  ]
end

#genus_speciesString?

Returns parse and only return what is assumed to be genus/species, with a wildcard in front.

Returns:

  • (String, nil)

    parse and only return what is assumed to be genus/species, with a wildcard in front



335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/queries/taxon_name/autocomplete.rb', line 335

def genus_species
  p = TaxonWorks::Vendor::Biodiversity::Result.new
  p.name = query_string
  r = p.parse

  a = p.genus
  b = p.species

  if a && b
    a + '%' + b
  else
    nil
  end
end

#is_typeArel::Nodes::<>?

and clause

Returns:

  • (Arel::Nodes::<>, nil)


112
113
114
115
# File 'lib/queries/taxon_name/autocomplete.rb', line 112

def is_type
  return nil if type.empty?
  table[:type].eq_any(type)
end

#or_andArel:Nodes

Returns:

  • (Arel:Nodes)


87
88
89
90
91
92
93
94
95
96
# File 'lib/queries/taxon_name/autocomplete.rb', line 87

def or_and
  a = or_clauses
  b = and_clauses

  if a && b
    a.and(b)
  else
    a
  end
end

#or_clausesArel:Nodes

Returns:

  • (Arel:Nodes)


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/queries/taxon_name/autocomplete.rb', line 48

def or_clauses
  clauses = []

  clauses.push exactly_named if exact

  clauses += [
    only_ids,
    cached_facet,
    with_cached_author_year,
  ] unless exact

  clauses.compact!

  a = clauses.shift
  clauses.each do |b|
    a = a.or(b)
  end
  a
end

#taxon_name_hierarchies_tableArel::Table

Returns:

  • (Arel::Table)


358
359
360
# File 'lib/queries/taxon_name/autocomplete.rb', line 358

def taxon_name_hierarchies_table
  Arel::Table.new('taxon_name_hierarchies')
end

#valid_stateArel::Nodes::<>?

and clause

Returns:

  • (Arel::Nodes::<>, nil)


105
106
107
108
# File 'lib/queries/taxon_name/autocomplete.rb', line 105

def valid_state
  return nil if @valid.nil?
  valid ? table[:id].eq(table[:cached_valid_taxon_name_id]) : table[:id].not_eq(table[:cached_valid_taxon_name_id])
end

#where_sqlString

Returns:

  • (String)


99
100
101
# File 'lib/queries/taxon_name/autocomplete.rb', line 99

def where_sql
  with_project_id.and(or_and).to_sql
end

#with_cached_author_yearArel::Nodes::Matches

Returns:

  • (Arel::Nodes::Matches)


363
364
365
# File 'lib/queries/taxon_name/autocomplete.rb', line 363

def with_cached_author_year
  table[:cached_author_year].matches_any(terms)
end

#with_nomenclature_groupArel::Nodes::Grouping?

Returns and clause.

Returns:

  • (Arel::Nodes::Grouping, nil)

    and clause



126
127
128
129
# File 'lib/queries/taxon_name/autocomplete.rb', line 126

def with_nomenclature_group
  return nil if nomenclature_group.empty?
  table[:rank_class].matches_any(nomenclature_group)
end

#with_parent_idArel::Nodes::<>?

and clause, limit to ancestors or [ids]

Returns:

  • (Arel::Nodes::<>, nil)


119
120
121
122
# File 'lib/queries/taxon_name/autocomplete.rb', line 119

def with_parent_id
  return nil if parent_id.empty?
  taxon_name_hierarchies_table[:ancestor_id].eq_any(parent_id)
end