Module: ActiveRecord::Refined::AST::Predications

Included in:
Aggregate, Arithmetic, Bitwise, BitwiseNot, Case, Cast, Column, DatetimeValueFunction, Extract, Function, JsonPath, JsonSet, Over, Value
Defined in:
lib/active_record/refined/ast.rb

Overview

Predicate builders shared by symbols, qualified columns and expressions. Imported into the Symbol refinement with Refinement#import_methods, so every method must be defined with def.

Instance Method Summary collapse

Instance Method Details

#!=(other) ⇒ Object



49
50
51
52
53
54
# File 'lib/active_record/refined/ast.rb', line 49

def !=(other)
  if other.nil?
    raise ArgumentError, "!= does not take nil; use !null? instead"
  end
  Comparison.new(self, :!=, other)
end

#!~(pattern) ⇒ Object



76
77
78
# File 'lib/active_record/refined/ast.rb', line 76

def !~(pattern)
  Match.new(self, pattern, negated: true)
end

#<(other) ⇒ Object



64
65
66
# File 'lib/active_record/refined/ast.rb', line 64

def <(other)
  Comparison.new(self, :<, other)
end

#<=(other) ⇒ Object



68
69
70
# File 'lib/active_record/refined/ast.rb', line 68

def <=(other)
  Comparison.new(self, :<=, other)
end

#==(other) ⇒ Object

and != mean SQL = and <>, and = NULL is never true there, so nil

is rejected rather than silently rewritten to IS NULL. null? builds its node directly and stays clear of this check.



42
43
44
45
46
47
# File 'lib/active_record/refined/ast.rb', line 42

def ==(other)
  if other.nil?
    raise ArgumentError, "== does not take nil; use null? instead"
  end
  Comparison.new(self, :==, other)
end

#=~(pattern) ⇒ Object



72
73
74
# File 'lib/active_record/refined/ast.rb', line 72

def =~(pattern)
  Match.new(self, pattern)
end

#>(other) ⇒ Object



56
57
58
# File 'lib/active_record/refined/ast.rb', line 56

def >(other)
  Comparison.new(self, :>, other)
end

#>=(other) ⇒ Object



60
61
62
# File 'lib/active_record/refined/ast.rb', line 60

def >=(other)
  Comparison.new(self, :>=, other)
end

#between?(min, max) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/active_record/refined/ast.rb', line 121

def between?(min, max)
  In.new(self, min..max)
end

#bury(*path, value) ⇒ Object

What dig reads, bury sets: the last argument is the value and the rest are the path to it. The document comes back changed rather than being written anywhere, which update_all is for.



230
231
232
# File 'lib/active_record/refined/ast.rb', line 230

def bury(*path, value)
  JsonSet.new(self, path, value)
end

#casecmp?(value) ⇒ Boolean

Case-insensitive equality, folded on both sides rather than left to the collation, so it means the same thing on every adapter.

Returns:

  • (Boolean)


154
155
156
157
158
159
160
# File 'lib/active_record/refined/ast.rb', line 154

def casecmp?(value)
  if value.nil?
    raise ArgumentError, "casecmp? does not take nil; use null? instead"
  end
  Comparison.new(Function.new("LOWER", [self]), :==,
                 Function.new("LOWER", [value]))
end

#contains?(value) ⇒ Boolean

Whether the document holds what is given, which SQL calls containment. SQLite has no equivalent.

Returns:

  • (Boolean)


236
237
238
# File 'lib/active_record/refined/ast.rb', line 236

def contains?(value)
  JsonContains.new(self, value)
end

#dig(*path) ⇒ Object

Reading inside a JSON document, by the name of what Hash does. A string or symbol steps into an object, an integer into an array, and what comes back is the value rather than the JSON, since that is what a comparison wants. dig_json keeps it JSON, for a document to be dug into further or compared whole.



219
220
221
# File 'lib/active_record/refined/ast.rb', line 219

def dig(*path)
  JsonPath.new(self, path)
end

#dig_json(*path) ⇒ Object



223
224
225
# File 'lib/active_record/refined/ast.rb', line 223

def dig_json(*path)
  JsonPath.new(self, path, as_json: true)
end

#distinct_from?(value) ⇒ Boolean

Null-safe comparison: unlike = and <>, these treat NULL as a value, so not_distinct_from? is the one equality that may take nil.

Returns:

  • (Boolean)


164
165
166
# File 'lib/active_record/refined/ast.rb', line 164

def distinct_from?(value)
  DistinctFrom.new(self, value, negated: true)
end

#end_with?(*suffixes) ⇒ Boolean

Returns:

  • (Boolean)


179
180
181
182
183
184
# File 'lib/active_record/refined/ast.rb', line 179

def end_with?(*suffixes)
  if suffixes.empty?
    raise ArgumentError, "end_with? needs at least one suffix"
  end
  Like.any(self, suffixes.map {|suffix| "%#{Like.escape(suffix)}" })
end

#false?Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/active_record/refined/ast.rb', line 105

def false?
  TruthValue.new(self, false)
end

#ilike?(pattern) ⇒ Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/active_record/refined/ast.rb', line 144

def ilike?(pattern)
  Like.new(self, pattern, nil, case_sensitive: false)
end

#in?(values) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/active_record/refined/ast.rb', line 113

def in?(values)
  In.new(self, values)
end

#include?(substring) ⇒ Boolean

Returns:

  • (Boolean)


186
187
188
# File 'lib/active_record/refined/ast.rb', line 186

def include?(substring)
  Like.new(self, "%#{Like.escape(substring)}%", Like::ESCAPE)
end

#intersect?(elements) ⇒ Boolean

Returns:

  • (Boolean)


210
211
212
# File 'lib/active_record/refined/ast.rb', line 210

def intersect?(elements)
  ArrayPredicate.new(self, :"&&", ArrayPredicate.elements(elements, "intersect?"))
end

#key?(key) ⇒ Boolean

Whether the key is there at all, as Hash#key? asks. Hash has has_key? too; one name is enough, and this is the one Ruby's own style prefers.

Returns:

  • (Boolean)


243
244
245
# File 'lib/active_record/refined/ast.rb', line 243

def key?(key)
  JsonHasKey.new(self, key)
end

#like?(pattern) ⇒ Boolean

Returns:

  • (Boolean)


136
137
138
# File 'lib/active_record/refined/ast.rb', line 136

def like?(pattern)
  Like.new(self, pattern)
end

#member?(element) ⇒ Boolean

The array comparisons carry the meaning of their Ruby namesakes. member? is Enumerable's element test, so an Array argument is rejected rather than quietly meaning something Array#member? does not; whole-array comparisons go by the Set and Array names.

Returns:

  • (Boolean)


194
195
196
197
198
199
200
# File 'lib/active_record/refined/ast.rb', line 194

def member?(element)
  if element.is_a?(::Array) || element.is_a?(::Set)
    raise ArgumentError,
      "member? takes a single element; use superset? to require every element"
  end
  ArrayPredicate.new(self, :"@>", [element])
end

#not_between?(min, max) ⇒ Boolean

Returns:

  • (Boolean)


125
126
127
# File 'lib/active_record/refined/ast.rb', line 125

def not_between?(min, max)
  In.new(self, min..max, negated: true)
end

#not_distinct_from?(value) ⇒ Boolean

Returns:

  • (Boolean)


168
169
170
# File 'lib/active_record/refined/ast.rb', line 168

def not_distinct_from?(value)
  DistinctFrom.new(self, value)
end

#not_false?Boolean

Returns:

  • (Boolean)


109
110
111
# File 'lib/active_record/refined/ast.rb', line 109

def not_false?
  TruthValue.new(self, false, negated: true)
end

#not_ilike?(pattern) ⇒ Boolean

Returns:

  • (Boolean)


148
149
150
# File 'lib/active_record/refined/ast.rb', line 148

def not_ilike?(pattern)
  Like.new(self, pattern, nil, case_sensitive: false, negated: true)
end

#not_in?(values) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/active_record/refined/ast.rb', line 117

def not_in?(values)
  In.new(self, values, negated: true)
end

#not_like?(pattern) ⇒ Boolean

Returns:

  • (Boolean)


140
141
142
# File 'lib/active_record/refined/ast.rb', line 140

def not_like?(pattern)
  Like.new(self, pattern, negated: true)
end

#not_null?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/active_record/refined/ast.rb', line 88

def not_null?
  Comparison.new(self, :!=, nil)
end

#not_true?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/active_record/refined/ast.rb', line 101

def not_true?
  TruthValue.new(self, true, negated: true)
end

#null?Boolean

! negates any predicate, so these are here for the four that SQL spells for itself: IS NOT NULL rather than NOT (... IS NULL), and likewise NOT IN and NOT LIKE. They mean the same thing either way, including when the column is NULL; what they save is the reading.

Returns:

  • (Boolean)


84
85
86
# File 'lib/active_record/refined/ast.rb', line 84

def null?
  Comparison.new(self, :==, nil)
end

#start_with?(*prefixes) ⇒ Boolean

Returns:

  • (Boolean)


172
173
174
175
176
177
# File 'lib/active_record/refined/ast.rb', line 172

def start_with?(*prefixes)
  if prefixes.empty?
    raise ArgumentError, "start_with? needs at least one prefix"
  end
  Like.any(self, prefixes.map {|prefix| "#{Like.escape(prefix)}%" })
end

#subset?(elements) ⇒ Boolean

Returns:

  • (Boolean)


206
207
208
# File 'lib/active_record/refined/ast.rb', line 206

def subset?(elements)
  ArrayPredicate.new(self, :"<@", ArrayPredicate.elements(elements, "subset?"))
end

#superset?(elements) ⇒ Boolean

Returns:

  • (Boolean)


202
203
204
# File 'lib/active_record/refined/ast.rb', line 202

def superset?(elements)
  ArrayPredicate.new(self, :"@>", ArrayPredicate.elements(elements, "superset?"))
end

#true?Boolean

IS TRUE and IS FALSE differ from a comparison against the literal in what they make of NULL: flag = TRUE is itself NULL there, and a NULL predicate selects nothing, while these two answer false. So the difference shows in the negations: not_true? keeps the NULL rows that !(:flag == true) drops.

Returns:

  • (Boolean)


97
98
99
# File 'lib/active_record/refined/ast.rb', line 97

def true?
  TruthValue.new(self, true)
end

#when(value = nil, &block) ⇒ Object

CASE with this as the operand, compared against each when: :age.when(10).then(1).else(0). The other shape, where each when carries its own condition, starts at case_when.



132
133
134
# File 'lib/active_record/refined/ast.rb', line 132

def when(value = nil, &block)
  Case.new(self).when(value, &block)
end