Class: Queries::Query

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

Direct Known Subclasses

Autocomplete, Filter

Defined Under Namespace

Classes: Autocomplete, Filter

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#query_stringString

Returns:

  • (String)


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

def query_string
  @query_string
end

#termsArray

Returns an expanded search target arary, splitting query_string into a number of wild-carded values.

Returns:

  • (Array)

    an expanded search target arary, splitting query_string into a number of wild-carded values



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

def terms
  @terms
end

Class Method Details

.base_nameObject

Returns String like “otu” or “taxon_name”.

Returns:

  • String like “otu” or “taxon_name”



35
36
37
# File 'lib/queries/query.rb', line 35

def self.base_name
  referenced_klass.name.tableize.singularize # classify ?
end

.referenced_klassObject

Returns ApplicationRecord subclass e.g. Otu, TaxonName, the class this filter acts on.

Returns:

  • ApplicationRecord subclass e.g. Otu, TaxonName, the class this filter acts on



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

def self.referenced_klass
  ('::' + name.split('::').second).safe_constantize
end

Instance Method Details

#alphabetic_stringsArray

Returns:

  • (Array)


130
131
132
# File 'lib/queries/query.rb', line 130

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

#alphanumeric_stringsArray

Returns:

  • (Array)


135
136
137
# File 'lib/queries/query.rb', line 135

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

#base_nameObject



39
40
41
# File 'lib/queries/query.rb', line 39

def base_name
  self.class.base_name
end

#base_queryObject



47
48
49
# File 'lib/queries/query.rb', line 47

def base_query
  referenced_klass.select( referenced_klass.name.tableize + '.*'  )
end

#build_termsArray

Ultimately we should replace this concept with full text indexing.

Returns:

  • (Array)

    a reasonable (starting) interpretation of any query string



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

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

#cached_facetActiveRecord::Relation?

TODO: Used in taxon_name, source, identifier

Returns:

  • (ActiveRecord::Relation, nil)

    cached matches full query string wildcarded



158
159
160
161
162
# File 'lib/queries/query.rb', line 158

def cached_facet
  return nil if no_terms?
  # TODO: or is redundant with terms in many cases
  (table[:cached].matches_any(terms)).or(match_ordered_wildcard_pieces_in_cached)
end

#end_wildcardString

Returns:

  • (String)


120
121
122
# File 'lib/queries/query.rb', line 120

def end_wildcard
  query_string + '%'
end

#levenshtein_distance(attribute, value) ⇒ Object



139
140
141
142
143
# File 'lib/queries/query.rb', line 139

def levenshtein_distance(attribute, value)
  value = "'" + value.gsub(/'/, "''") + "'"
  a = ApplicationRecord.sanitize_sql(value)
  Arel::Nodes::NamedFunction.new('levenshtein', [table[attribute], Arel::Nodes::SqlLiteral.new(a) ] )
end

#match_ordered_wildcard_pieces_in_cachedArel::Nodes::Matches

Returns:

  • (Arel::Nodes::Matches)


151
152
153
# File 'lib/queries/query.rb', line 151

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

#no_terms?Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/queries/query.rb', line 110

def no_terms?
  terms.blank?
end

#referenced_klassObject



51
52
53
# File 'lib/queries/query.rb', line 51

def referenced_klass
  self.class.referenced_klass
end

#referenced_klass_except(query) ⇒ Object

This is an exists equivalent to saying all referenced_klass except those

in the related query

Parameters:

  • query

    A query that returns referenced_klass records



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

def referenced_klass_except(query)
  t = "q_#{table.name}"
  s = "with #{t} AS (" + query.to_sql + ')' +
  referenced_klass.joins("LEFT JOIN #{t} AS #{t}1 on #{t}1.id = #{table.name}.id").to_sql
  referenced_klass.from("(#{s}) as #{table.name}")
end

#referenced_klass_intersection(queries) ⇒ Object

Parameters:

  • queries

    Array of [nil, merge clauses]



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/queries/query.rb', line 62

def referenced_klass_intersection(queries)
  q = queries.compact

  # We can return this directly, though we get conflicts with `from:` on merge clauses
  z = referenced_klass.from("( #{q.collect{|i| '(' + i.to_sql + ')' }.join(' INTERSECT ')}) as #{table.name}")

  # Probably need a global counter, and this may not be needed
  s = Utilities::Strings.random_string(5)
  a = table.name + s

  # Here we probably get conflicts with join: clauses
  referenced_klass.joins("INNER JOIN ( #{z.to_sql}  ) AS #{a} ON #{a}.id = #{table.name}.id")
end

#referenced_klass_union(queries) ⇒ Object

Parameters:

  • queries

    Array of [nil, merge clauses]



56
57
58
59
# File 'lib/queries/query.rb', line 56

def referenced_klass_union(queries)
  q = queries.compact
  referenced_klass.from("( #{q.collect{|i| '(' + i.to_sql + ')' }.join(' UNION ')}) as #{table.name}")
end

#start_and_end_wildcardString

Returns:

  • (String)


125
126
127
# File 'lib/queries/query.rb', line 125

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

#start_wildcardString

Returns:

  • (String)


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

def start_wildcard
  '%' + query_string
end

#tableObject



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

def table
  referenced_klass.arel_table
end

#wildcard_piecesString, TODO: nil

TODO: This is bad, it should return nil, not ‘NothingToMatch’

Returns:

  • (String, TODO: nil)

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



167
168
169
170
171
# File 'lib/queries/query.rb', line 167

def wildcard_pieces
  a = '%' + query_string.gsub(/[^[[:word:]]]+/, '%') + '%' ### DD: if query_string is cyrilic or diacritics, it returns '%%%'
  a = 'NothingToMatch' if a.gsub('%','').gsub(' ', '').blank?
  a
end