Class: JSI::ObjectJSONCoder

Inherits:
Object
  • Object
show all
Defined in:
lib/jsi/schema_instance_json_coder.rb

Overview

this is a ActiveRecord serialization class intended to store JSON in the database column and expose a ruby class once loaded on a model instance. this allows for better ruby idioms to access to properties, and definition of related methods on the loaded class.

the first argument, loaded_class, is the class which will be used to instantiate the column data. properties of the loaded class will correspond to keys of the json object in the database.

the column data may be either a single instance of the loaded class (represented as one json object) or an array of them (represented as a json array of json objects), indicated by the keyword argument array.

the column behind the attribute may be an actual JSON column (postgres json or jsonb - hstore should work too if you only have string attributes) or a serialized string, indicated by the keyword argument string.

Direct Known Subclasses

SchemaInstanceJSONCoder, StructJSONCoder

Defined Under Namespace

Classes: DumpError, Error, LoadError

Instance Method Summary collapse

Constructor Details

#initialize(loaded_class, string: false, array: false, next_coder: nil) ⇒ ObjectJSONCoder

Returns a new instance of ObjectJSONCoder.



26
27
28
29
30
31
32
33
34
35
# File 'lib/jsi/schema_instance_json_coder.rb', line 26

def initialize(loaded_class, string: false, array: false, next_coder: nil)
  @loaded_class = loaded_class
  # this notes the order of the keys as they were in the json, used by dump_object to generate
  # json that is equivalent to the json/jsonifiable that came in, so that AR's #changed_attributes
  # can tell whether the attribute has been changed.
  @loaded_class.send(:attr_accessor, :object_json_coder_keys_order)
  @string = string
  @array = array
  @next_coder = next_coder
end

Instance Method Details

#dump(object) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/jsi/schema_instance_json_coder.rb', line 52

def dump(object)
  object = @next_coder.dump(object) if @next_coder
  return nil if object.nil?
  jsonifiable = begin
    if @array
      unless object.respond_to?(:to_ary)
        raise DumpError, "expected array-like attribute; got: #{object.class}: #{object.inspect}"
      end
      object.map do |el|
        dump_object(el)
      end
    else
      dump_object(object)
    end
  end
  @string ? ::JSON.generate(jsonifiable) : jsonifiable
end

#load(column_data) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/jsi/schema_instance_json_coder.rb', line 37

def load(column_data)
  return nil if column_data.nil?
  data = @string ? ::JSON.parse(column_data) : column_data
  object = if @array
    unless data.respond_to?(:to_ary)
      raise TypeError, "expected array-like column data; got: #{data.class}: #{data.inspect}"
    end
    data.map { |el| load_object(el) }
  else
    load_object(data)
  end
  object = @next_coder.load(object) if @next_coder
  object
end