Module: Predicate::Factory

Extended by:
Factory
Included in:
Predicate, Expr, Factory
Defined in:
lib/predicate/factory.rb,
lib/predicate/postgres/ext/factory.rb

Instance Method Summary collapse

Instance Method Details

#_factor_predicate(arg, *mods) ⇒ Object



220
221
222
223
224
225
226
# File 'lib/predicate/factory.rb', line 220

def _factor_predicate(arg, *mods)
  expr = sexpr(arg)
  mods.each do |mod|
    expr.extend(mod)
  end
  expr
end

#and(left, right = nil) ⇒ Object

Builds a AND predicate using two sub predicates.

Please favor ‘Predicate#&` instead.



63
64
65
# File 'lib/predicate/factory.rb', line 63

def and(left, right = nil)
  _factor_predicate([:and, sexpr(left), sexpr(right)])
end

#comp(op, h) ⇒ Object

:nodoc:



84
85
86
# File 'lib/predicate/factory.rb', line 84

def comp(op, h)
  from_hash(h, op)
end

#contradictionObject

Factors a Predicate that captures False



12
13
14
# File 'lib/predicate/factory.rb', line 12

def contradiction
  _factor_predicate([:contradiction, false])
end

#empty(operand) ⇒ Object

Factors an EMPTY predicate that responds true when its operand is something empty.

Default evaluation uses ruby ‘empty?` method.



144
145
146
# File 'lib/predicate/factory.rb', line 144

def empty(operand)
  _factor_predicate([:empty, sexpr(operand)])
end

#from_hash(h, op = :eq) ⇒ Object

Builds a AND predicate between all key/value pairs of the provided Hash, using the comparison operator specified.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/predicate/factory.rb', line 188

def from_hash(h, op = :eq)
  if h.empty?
    tautology
  else
    terms = h.to_a.map{|(k,v)|
      case v
      when Array  then [:in, sexpr(k), sexpr(v)]
      when Regexp then [:match, sexpr(k), sexpr(v) ]
      else             [op, sexpr(k), sexpr(v)]
      end
    }
    terms = terms.size == 1 ? terms.first : terms.unshift(:and)
    _factor_predicate terms
  end
end

#h(h) ⇒ Object

Factors a predicate from a mapping between variables and values. This typically generates a AND(EQ) predicate, but a value can be an Array (IN) or a Regexp (MATCH).



167
168
169
# File 'lib/predicate/factory.rb', line 167

def h(h)
  from_hash(h, :eq)
end

#has_size(left, right) ⇒ Object

Factors a SIZE predicate that responds true when its operand has a size meeting the right constraint (typically a Range literal)



151
152
153
# File 'lib/predicate/factory.rb', line 151

def has_size(left, right)
  _factor_predicate([:has_size, sexpr(left), sexpr(right)])
end

#identifier(name) ⇒ Object

Factors a Predicate for a free variable whose name is provided. If the variable is a Boolean variable, this is a valid Predicate, otherwise it must be used in a higher-level expression.



41
42
43
# File 'lib/predicate/factory.rb', line 41

def identifier(name)
  _factor_predicate([:identifier, name])
end

#in(left, right) ⇒ Object Also known as: among

Factors a IN predicate between a variable and either a list of values of another variable.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/predicate/factory.rb', line 100

def in(left, right)
  case right
  when Range
    return contradiction if right.size == 0
    rl = gte(left, right.begin)
    rr = right.exclude_end? ? lt(left, right.end) : lte(left, right.end)
    self.and(rl, rr)
  else
    left, right = sexpr(left), sexpr(right)
    if right.literal? && right.empty_value?
      contradiction
    else
      _factor_predicate([:in, left, right])
    end
  end
end

#literal(literal) ⇒ Object

Factors a Literal node for some ruby value.



19
20
21
# File 'lib/predicate/factory.rb', line 19

def literal(literal)
  _factor_predicate([:literal, literal])
end

#match(left, right, options) ⇒ Object

Factors a MATCH predicate between a variable and a literal or another variable.

Matching options can be passes and are specific to the actual usage of the library.



134
135
136
137
138
# File 'lib/predicate/factory.rb', line 134

def match(left, right, options)
  s = [:match, sexpr(left), sexpr(right)]
  s << options unless options.nil?
  _factor_predicate(s)
end

#native(arg) ⇒ Object

Factors a predicate for a ruby Proc that returns truth-value for a single argument.



173
174
175
# File 'lib/predicate/factory.rb', line 173

def native(arg)
  _factor_predicate([:native, arg])
end

#not(operand) ⇒ Object

Negates an existing predicate.

Please favor ‘Predicate#!` instead.



77
78
79
# File 'lib/predicate/factory.rb', line 77

def not(operand)
  _factor_predicate([:not, sexpr(operand)])
end

#opaque(arg) ⇒ Object

Converts ‘arg` to an opaque predicate, whose semantics depends on the actual usage of the library.



179
180
181
# File 'lib/predicate/factory.rb', line 179

def opaque(arg)
  _factor_predicate([:opaque, arg])
end

#or(left, right = nil) ⇒ Object

Builds a OR predicate using two sub predicates.

Please favor ‘Predicate#|` instead.



70
71
72
# File 'lib/predicate/factory.rb', line 70

def or(left, right = nil)
  _factor_predicate([:or, sexpr(left), sexpr(right)])
end

#pg_array_empty(operand, type = :varchar) ⇒ Object



20
21
22
23
24
25
26
# File 'lib/predicate/postgres/ext/factory.rb', line 20

def pg_array_empty(operand, type = :varchar)
  _factor_predicate([
    :pg_empty,
    sexpr(operand),
    type
  ], Postgres::PgArray::Empty)
end

#pg_array_literal(value, type = :varchar) ⇒ Object



3
4
5
6
7
8
9
# File 'lib/predicate/postgres/ext/factory.rb', line 3

def pg_array_literal(value, type = :varchar)
  _factor_predicate([
    :pg_array_literal,
    value,
    type
  ], Postgres::PgArray::Literal)
end

#pg_array_overlaps(left, right, type = :varchar) ⇒ Object



11
12
13
14
15
16
17
18
# File 'lib/predicate/postgres/ext/factory.rb', line 11

def pg_array_overlaps(left, right, type = :varchar)
  _factor_predicate([
    :pg_array_overlaps,
    sexpr(left),
    sexpr(right),
    type
  ], Postgres::PgArray::Overlaps)
end

#placeholderObject

Builds and returns a placeholder that can be used everywhere a literal can be used. Placeholders can be bound later, using ‘Predicate#bind`.



54
55
56
# File 'lib/predicate/factory.rb', line 54

def placeholder
  Placeholder.new
end

#qualified_identifier(qualifier, name) ⇒ Object

Factors a Predicate for a qualified free variable. Same remark as in ‘identifier`.



47
48
49
# File 'lib/predicate/factory.rb', line 47

def qualified_identifier(qualifier, name)
  _factor_predicate([:qualified_identifier, qualifier, name])
end

#sexpr(expr) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/predicate/factory.rb', line 206

def sexpr(expr)
  case expr
  when Expr        then expr
  when Predicate   then expr.expr
  when TrueClass   then Grammar.sexpr([:tautology, true])
  when FalseClass  then Grammar.sexpr([:contradiction, false])
  when Symbol      then Grammar.sexpr([:identifier, expr])
  when Proc        then Grammar.sexpr([:native, expr])
  when SexprLike   then Grammar.sexpr(expr)
  else
    Grammar.sexpr([:literal, expr])
  end
end

#tautologyObject

Factors a Predicate that captures True



7
8
9
# File 'lib/predicate/factory.rb', line 7

def tautology
  _factor_predicate([:tautology, true])
end

#var(formaldef, semantics = :dig) ⇒ Object

Factors a var node, using a given extractor semantics



26
27
28
# File 'lib/predicate/factory.rb', line 26

def var(formaldef, semantics = :dig)
  _factor_predicate([:var, formaldef, semantics])
end

#vars(*args) ⇒ Object

Factors a couple of variables at once. The semantics can be passed as a Symbol as last argument and defaults to :dig



32
33
34
35
# File 'lib/predicate/factory.rb', line 32

def vars(*args)
  args << :dig unless args.last.is_a?(Symbol)
  args[0...-1].map{|v| var(v, args.last) }
end