Class: Torque::PostgreSQL::Adapter::OID::Struct

Inherits:
ActiveRecord::Type::Json
  • Object
show all
Defined in:
lib/torque/postgresql/adapter/oid/struct.rb

Direct Known Subclasses

StructList

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass, type: :jsonb, backfill: nil) ⇒ Struct

Returns a new instance of Struct.



21
22
23
24
25
26
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 21

def initialize(klass, type: :jsonb, backfill: nil)
  super()
  @klass = klass
  @type = type
  @backfill = backfill
end

Instance Attribute Details

#backfillObject (readonly)

Returns the value of attribute backfill.



8
9
10
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 8

def backfill
  @backfill
end

#klassObject (readonly)

Returns the value of attribute klass.



8
9
10
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 8

def klass
  @klass
end

#typeObject (readonly)

Returns the value of attribute type.



8
9
10
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 8

def type
  @type
end

Class Method Details

.state(value) ⇒ Object

A comparable representation of a struct-backed value, based on the values it exposes instead of the document it generates, so that non-deterministic types like encrypted attributes stay stable



13
14
15
16
17
18
19
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 13

def self.state(value)
  case value
  when nil then nil
  when ::Array then value.map { |item| state(item) }
  else value.respond_to?(:attributes) ? [value.class, value.attributes] : value
  end
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



93
94
95
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 93

def ==(other)
  other.class == self.class && other.klass == klass && other.type == type
end

#blank_documentObject



89
90
91
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 89

def blank_document
  {}
end

#cast(value) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 28

def cast(value)
  case value
  when klass then value
  when ::Hash then build(value)
  when ::String then cast(parse(value))
  else value
  end
end

#changed?(old_value, new_value, _new_value_before_cast) ⇒ Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 49

def changed?(old_value, new_value, _new_value_before_cast)
  Struct.state(old_value) != Struct.state(new_value)
end

#changed_in_place?(raw_old_value, new_value) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 53

def changed_in_place?(raw_old_value, new_value)
  Struct.state(without_backfill.deserialize(raw_old_value)) != Struct.state(new_value)
end

#deserialize(value) ⇒ Object



37
38
39
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 37

def deserialize(value)
  build(parse(value), from_database: true, blank: true)
end

#document(value) ⇒ Object

The hash that represents the value on the database, holding only the properties that were actually written to it. Properties backed by another struct are kept as documents, so that they are not stored as an encoded string inside this one



78
79
80
81
82
83
84
85
86
87
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 78

def document(value)
  set = value.instance_variable_get(:@attributes)
  set.keys.to_h do |name|
    attribute = set[name]
    type = attribute.type

    next [name, type.document_for(attribute.value)] if type.is_a?(Struct)
    [name, attribute.value_for_database]
  end
end

#document_for(value) ⇒ Object

The value as it goes inside another document, which is a hash, and not the encoded JSON that a column receives



70
71
72
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 70

def document_for(value)
  value.nil? ? nil : document(value)
end

#empty?(value) ⇒ Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 64

def empty?(value)
  document(value).empty?
end

#hashObject



98
99
100
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 98

def hash
  [self.class, klass, type].hash
end

#serialize(value) ⇒ Object



41
42
43
44
45
46
47
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 41

def serialize(value)
  case value
  when klass then empty?(value) ? nil : super(document(value))
  when nil then nil
  else super
  end
end

#without_backfillObject

The same type, but reading documents exactly as they are stored, so that backfilled properties are seen as changes



59
60
61
62
# File 'lib/torque/postgresql/adapter/oid/struct.rb', line 59

def without_backfill
  return self if backfill.nil?
  @without_backfill ||= self.class.new(klass, type: type)
end