Class: ActiveJsonModel::ActiveRecordType

Inherits:
ActiveRecord::Type::Value
  • Object
show all
Includes:
ActiveModel::Type::Helpers::Mutable
Defined in:
lib/active_json_model/active_record_type.rb

Overview

Allows instances of ActiveJsonModels to be serialized JSONB columns for ActiveRecord models.

class Credentials < ::ActiveJsonModel
  def self.attribute_type
    ActiveRecordType.new(Credentials)
  end
end

class Integration < ActiveRecord::Base
  attribute :credentials, Credentials.attribute_type
end

This is based on: jetrockets.pro/blog/rails-5-attributes-api-value-objects-and-jsonb

Direct Known Subclasses

ActiveRecordEncryptedType

Instance Method Summary collapse

Constructor Details

#initialize(clazz) ⇒ ActiveRecordType

Create an instance bound to a ActiveJsonModel class.

e.g.

class Credentials < ::ActiveJsonModel; end
#...
return ActiveRecordType.new(Credentials)


33
34
35
# File 'lib/active_json_model/active_record_type.rb', line 33

def initialize(clazz)
  @clazz = clazz
end

Instance Method Details

#cast(value) ⇒ Object



41
42
43
44
45
46
47
# File 'lib/active_json_model/active_record_type.rb', line 41

def cast(value)
  if value.is_a?(@clazz)
    value
  elsif value.is_a?(::Array)
    @clazz.load(value)
  end
end

#changed_in_place?(raw_old_value, new_value) ⇒ Boolean

Override to handle issues comparing hashes encoded as strings, where the actual order doesn’t matter.

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/active_json_model/active_record_type.rb', line 70

def changed_in_place?(raw_old_value, new_value)
  if raw_old_value.nil? || new_value.nil?
    raw_old_value == new_value
  else
    # Decode is necessary because postgres can change the order of hashes. Round-tripping on the new value side
    # is to handle any dates that might be rendered as strings.
    decoded_raw = ::ActiveSupport::JSON.decode(raw_old_value)
    round_tripped_new = ::ActiveSupport::JSON.decode(new_value.class.dump(new_value))

    decoded_raw != round_tripped_new
  end
end

#deserialize(value) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/active_json_model/active_record_type.rb', line 49

def deserialize(value)
  if String === value
    decoded = ::ActiveSupport::JSON.decode(value) rescue nil
    @clazz.load(decoded)
  else
    super
  end
end

#serialize(value) ⇒ Object



58
59
60
61
62
63
64
65
66
67
# File 'lib/active_json_model/active_record_type.rb', line 58

def serialize(value)
  case value
  when @clazz
    ::ActiveSupport::JSON.encode(@clazz.dump(value))
  when Array, Hash
    ::ActiveSupport::JSON.encode(value)
  else
    super
  end
end

#typeObject



37
38
39
# File 'lib/active_json_model/active_record_type.rb', line 37

def type
  :jsonb
end