Class: Torque::PostgreSQL::PredicateBuilder::StructHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/torque/postgresql/predicate_builder/struct_handler.rb

Overview

Turns a hash of properties into a proper set of conditions over the document that holds them, handing each of them back to the predicate builder so that the whole where vocabulary works inside a struct

Constant Summary collapse

PLAIN_TYPES =

Properties are extracted as text, so only the ones whose type has a counterpart on the database are casted before being compared

%i[string text].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(predicate_builder) ⇒ StructHandler

Returns a new instance of StructHandler.



23
24
25
# File 'lib/torque/postgresql/predicate_builder/struct_handler.rb', line 23

def initialize(predicate_builder)
  @predicate_builder = predicate_builder
end

Class Method Details

.candidate?(value, type) ⇒ Boolean

Only a hash describes properties, everything else is left alone so that whole documents are still compared as documents

Returns:

  • (Boolean)


17
18
19
20
# File 'lib/torque/postgresql/predicate_builder/struct_handler.rb', line 17

def candidate?(value, type)
  value.is_a?(::Hash) && type.is_a?(Adapter::OID::Struct) &&
    !type.is_a?(Adapter::OID::StructList)
end

Instance Method Details

#call(attribute, struct, value) ⇒ Object

Raises:

  • (ArgumentError)


27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/torque/postgresql/predicate_builder/struct_handler.rb', line 27

def call(attribute, struct, value)
  raise ArgumentError, <<~MSG.squish unless struct.type == :jsonb
    Unable to build a condition over "#{attribute.name}" because json
    columns cannot be queried by their properties. Use jsonb instead.
  MSG

  @struct = struct
  table = PredicateTable.new(self, attribute, Arel::Nodes::Property)
  nodes = predicate_builder.with(table).build_from_hash(value.stringify_keys)

  ::Arel::Nodes::Grouping.new(nodes.reduce(:and))
end

#type_of(name) ⇒ Object

The type of a single property, plus what it has to be casted to once it is extracted from the document as text

Raises:

  • (ArgumentError)


42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/torque/postgresql/predicate_builder/struct_handler.rb', line 42

def type_of(name)
  klass = @struct.klass
  name = name.to_s

  raise ArgumentError, <<~MSG.squish if klass.strict? && !klass.attribute_names.include?(name)
    Unable to build a condition for "#{name}" because it is not a
    declared property of #{klass.name}.
  MSG

  type = klass.attribute_types[name]
  [type, cast_for(type)]
end