Class: Typed::ActiveRecordSerializer

Inherits:
Serializer show all
Defined in:
lib/typed/active_record_serializer.rb

Constant Summary collapse

Input =
type_member { {fixed: T.untyped} }
Output =
type_member { {fixed: ActiveRecord::Base} }

Constants inherited from Serializer

Serializer::DeserializeResult, Serializer::Params

Instance Attribute Summary collapse

Attributes inherited from Serializer

#coercer_cache, #schema

Instance Method Summary collapse

Constructor Details

#initialize(schema:, model_class:) ⇒ ActiveRecordSerializer

Returns a new instance of ActiveRecordSerializer.



15
16
17
18
19
20
21
22
23
# File 'lib/typed/active_record_serializer.rb', line 15

def initialize(schema:, model_class:)
  @model_class = model_class
  @associations_by_name = T.let(
    model_class.reflect_on_all_associations.each_with_object({}) { |association, hsh| hsh[association.name.to_s] = association },
    T::Hash[String, T.untyped]
  )

  super(schema: schema)
end

Instance Attribute Details

#associations_by_nameObject (readonly)

Returns the value of attribute associations_by_name.



12
13
14
# File 'lib/typed/active_record_serializer.rb', line 12

def associations_by_name
  @associations_by_name
end

#model_classObject (readonly)

Returns the value of attribute model_class.



9
10
11
# File 'lib/typed/active_record_serializer.rb', line 9

def model_class
  @model_class
end

Instance Method Details

#deserialize(source) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/typed/active_record_serializer.rb', line 26

def deserialize(source)
  return Failure.new(DeserializeError.new("Cannot deserialize a non-ActiveRecord object.")) unless source.is_a?(ActiveRecord::Base)

  return Failure.new(DeserializeError.new("'#{source.class}' is not an instance of '#{model_class}'.")) unless source.class <= model_class

  creation_params = schema.fields.each_with_object(T.let({}, Params)) do |field, hsh|
    if source.respond_to?(field.name)
      value = source.send(field.name)
      hsh[field.name] = coerce_ar_value(field:, value:)
    end
  end

  deserialize_from_creation_params(creation_params)
end

#serialize(struct) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/typed/active_record_serializer.rb', line 42

def serialize(struct)
  return Failure.new(SerializeError.new("'#{struct.class}' cannot be serialized to target type of '#{schema.target}'.")) if struct.class != schema.target

  hsh = serialize_from_struct(struct:, should_serialize_values: true)
  column_names = model_class.column_names

  filtered = hsh.each_with_object(T.let({}, T::Hash[String, T.untyped])) do |(key, value), attrs|
    key_s = key.to_s
    association = associations_by_name[key_s]

    if association
      attrs[key_s] = association.klass.new(value) if column_names.include?(association.foreign_key)
    elsif column_names.include?(key_s)
      attrs[key_s] = value
    end
  end

  Success.new(model_class.new(filtered))
rescue ActiveRecord::AssociationTypeMismatch => e
  Failure.new(SerializeError.new(e.message))
end