Class: AttrJson::Type::ContainerAttribute

Inherits:
Object
  • Object
show all
Defined in:
lib/attr_json/type/container_attribute.rb

Overview

A type that gets applied to the AR container/store jsonb attribute, to do serialization/deserialization/cast using declared attr_jsons, to json-able values, before calling super to original json-type, which will actually serialize/deserialize the json.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, container_attribute) ⇒ ContainerAttribute

Returns a new instance of ContainerAttribute.



15
16
17
18
# File 'lib/attr_json/type/container_attribute.rb', line 15

def initialize(model, container_attribute)
  @model = model
  @container_attribute = container_attribute.to_s
end

Instance Attribute Details

#container_attributeObject (readonly)

Returns the value of attribute container_attribute.



14
15
16
# File 'lib/attr_json/type/container_attribute.rb', line 14

def container_attribute
  @container_attribute
end

#modelObject (readonly)

Returns the value of attribute model.



14
15
16
# File 'lib/attr_json/type/container_attribute.rb', line 14

def model
  @model
end

Instance Method Details

#cast(v) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/attr_json/type/container_attribute.rb', line 19

def cast(v)
  # this seems to be rarely/never called by AR, not sure where if ever.
  h = super || {}
  model.attr_json_registry.definitions.each do |attr_def|
    next unless container_attribute.to_s == attr_def.container_attribute.to_s

    if h.has_key?(attr_def.store_key)
      h[attr_def.store_key] = attr_def.cast(h[attr_def.store_key])
    elsif attr_def.has_default?
      h[attr_def.store_key] = attr_def.provide_default!
    end
  end
  h
end

#changed_in_place?(raw_old_value, new_value) ⇒ Boolean

Just like superclass, but we tell deserialize to NOT apply defaults, so we can consider default-application to be a change.

Returns:

  • (Boolean)


63
64
65
# File 'lib/attr_json/type/container_attribute.rb', line 63

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

#deserialize(v, with_defaults: true) ⇒ Object

optional with_defaults arg is our own, not part of ActiveModel::Type API, used by #changed_in_place? so we can consider default application to be a change.



47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/attr_json/type/container_attribute.rb', line 47

def deserialize(v, with_defaults: true)
  h = super(v) || {}
  model.attr_json_registry.definitions.each do |attr_def|
    next unless container_attribute.to_s == attr_def.container_attribute.to_s

    if h.has_key?(attr_def.store_key)
      h[attr_def.store_key] = attr_def.deserialize(h[attr_def.store_key])
    elsif with_defaults && attr_def.has_default?
      h[attr_def.store_key] = attr_def.provide_default!
    end
  end
  h
end

#serialize(v) ⇒ Object



33
34
35
36
37
38
39
40
41
42
# File 'lib/attr_json/type/container_attribute.rb', line 33

def serialize(v)
  if v.nil?
    return super
  end

  super(v.collect do |key, value|
    attr_def = model.attr_json_registry.store_key_lookup(container_attribute, key)
    [key, attr_def ? attr_def.serialize(value) : value]
  end.to_h)
end