Class: Torque::PostgreSQL::Adapter::OID::Composite

Inherits:
ActiveModel::Type::Value
  • Object
show all
Defined in:
lib/torque/postgresql/adapter/oid/composite.rb

Constant Summary collapse

ARRAY =
ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array
DATA =
ARRAY::Data
ENCODER =
PG::TextEncoder::Record.new
DECODER =
PG::TextDecoder::Record.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Composite

Returns a new instance of Composite.



28
29
30
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 28

def initialize(name)
  @name = name.to_s.freeze
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



13
14
15
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 13

def name
  @name
end

Class Method Details

.create(row, type_map) ⇒ Object



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

def self.create(row, type_map)
  oid_klass = new(row['typname'])
  type_map.register_type(row['oid'].to_i, oid_klass)
  type_map.register_type(row['typarray'].to_i, ARRAY.new(oid_klass, row['typdelim']))
end

.from(type) ⇒ Object

The composite type behind the given type, if there is one, wrapped or not by an array



17
18
19
20
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 17

def self.from(type)
  type = type.subtype if type.is_a?(ARRAY)
  type if type.is_a?(self)
end

Instance Method Details

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



94
95
96
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 94

def ==(other)
  other.class == self.class && other.name == name
end

#cast(value) ⇒ Object



49
50
51
52
53
54
55
56
57
58
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 49

def cast(value)
  case value
  when klass then value
  when ::Hash then build(value)
  when DATA then deserialize(value)
  when ::String then deserialize(value)
  when ::Array then build(columns.keys.zip(value).to_h)
  else value
  end
end

#changed_in_place?(raw_old_value, new_value) ⇒ Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 90

def changed_in_place?(raw_old_value, new_value)
  deserialize(raw_old_value) != new_value
end

#columnsObject

The ordered list of columns of the composite type, as a hash of name and type



41
42
43
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 41

def columns
  klass.columns
end

#deserialize(value) ⇒ Object

A record that was already serialized comes back as the encoder and its values, which is how it is kept around for dirty tracking



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 62

def deserialize(value)
  return if value.nil?

  fields = value.is_a?(DATA) ? value.values : DECODER.decode(value)
  instance = klass.new
  set = attributes_of(instance)

  columns.each_key.with_index do |attr_name, idx|
    set.write_from_database(attr_name, fields[idx])
  end

  instance
end

#hashObject



99
100
101
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 99

def hash
  [self.class, name].hash
end

#klassObject

The class that represents the composite type, loaded in a lazy way. It cannot be memoized here because Rails freezes the types it resolves through the type map, so the lookup owns the cache



35
36
37
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 35

def klass
  Attributes::Composite.lookup(name)
end

#serialize(value) ⇒ Object

The record is handed over to the adapter as an encoder and its values, the same way arrays are, so that columns are type casted by the connection right before the record literal is built. Values come from the record itself, so that types declared by the class, like encrypted ones, are the ones being applied



81
82
83
84
85
86
87
88
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 81

def serialize(value)
  return if value.nil?

  set = attributes_of(cast(value))
  values = columns.each_key.map { |attr_name| set[attr_name].value_for_database }

  DATA.new(ENCODER, values)
end

#typeObject



45
46
47
# File 'lib/torque/postgresql/adapter/oid/composite.rb', line 45

def type
  :composite
end