Module: JSONAPI::ActiveStorage::Deserialization

Defined in:
lib/json_api/active_storage/deserialization.rb

Class Method Summary collapse

Class Method Details

.append_blobs(attachment, blob_or_blobs) ⇒ Object



96
97
98
99
# File 'lib/json_api/active_storage/deserialization.rb', line 96

def append_blobs(attachment, blob_or_blobs)
  existing_blobs = attachment.attached? ? attachment.blobs.to_a : []
  attachment.attach(existing_blobs + blob_or_blobs)
end

.append_only_enabled?(attachment_name, definition) ⇒ Boolean

Returns:

  • (Boolean)


67
68
69
70
71
72
73
74
# File 'lib/json_api/active_storage/deserialization.rb', line 67

def append_only_enabled?(attachment_name, definition)
  return false unless definition

  relationship_def = find_relationship_definition(attachment_name, definition)
  return false unless relationship_def

  relationship_def[:options].fetch(:append_only, false)
end

.attach_files(record, attachment_params, definition: nil) ⇒ Object



19
20
21
22
23
24
25
# File 'lib/json_api/active_storage/deserialization.rb', line 19

def attach_files(record, attachment_params, definition: nil)
  return if attachment_params.empty?

  attachment_params.each do |name, blobs|
    attach_single(record, name, blobs, definition)
  end
end

.attach_single(record, name, blobs, definition) ⇒ Object



27
28
29
30
31
32
33
34
35
36
# File 'lib/json_api/active_storage/deserialization.rb', line 27

def attach_single(record, name, blobs, definition)
  attachment = record.public_send(name)
  if blobs.is_a?(Array)
    handle_has_many_attachment(attachment, blobs,
                               append_only: append_only_enabled?(name, definition),
                               attachment_name: name, definition:,)
  else
    handle_has_one_attachment(attachment, blobs, attachment_name: name, definition:)
  end
end

.extract_params_from_hash(params_hash, model_class) ⇒ Object



8
9
10
11
12
13
14
15
16
17
# File 'lib/json_api/active_storage/deserialization.rb', line 8

def extract_params_from_hash(params_hash, model_class)
  return {} unless defined?(::ActiveStorage)

  attachment_params = {}
  model_class.attachment_reflections.each_key do |attachment_name|
    attachment_name_str = attachment_name.to_s
    attachment_params[attachment_name] = params_hash[attachment_name_str] if params_hash.key?(attachment_name_str)
  end
  attachment_params
end

.find_blob_by_signed_id(signed_id) ⇒ Object



48
49
50
51
52
53
54
55
56
# File 'lib/json_api/active_storage/deserialization.rb', line 48

def find_blob_by_signed_id(signed_id)
  return nil if signed_id.blank?

  ::ActiveStorage::Blob.find_signed!(signed_id)
rescue ActiveSupport::MessageVerifier::InvalidSignature
  raise
rescue ActiveRecord::RecordNotFound => e
  raise ArgumentError, "Blob not found for signed ID: #{e.message}"
end

.find_relationship_definition(attachment_name, definition) ⇒ Object



76
77
78
79
80
# File 'lib/json_api/active_storage/deserialization.rb', line 76

def find_relationship_definition(attachment_name, definition)
  return nil unless definition.respond_to?(:relationship_definitions)

  definition.relationship_definitions.find { |r| r[:name].to_s == attachment_name.to_s }
end

.handle_empty_blobs(attachment, append_only, attachment_name, definition) ⇒ Object



90
91
92
93
94
# File 'lib/json_api/active_storage/deserialization.rb', line 90

def handle_empty_blobs(attachment, append_only, attachment_name, definition)
  return if append_only

  attachment.purge if purge_on_nil_enabled?(attachment_name, definition) && attachment.attached?
end

.handle_has_many_attachment(attachment, blob_or_blobs, append_only:, attachment_name:, definition:) ⇒ Object

Private helper methods



83
84
85
86
87
88
# File 'lib/json_api/active_storage/deserialization.rb', line 83

def handle_has_many_attachment(attachment, blob_or_blobs, append_only:, attachment_name:, definition:)
  return handle_empty_blobs(attachment, append_only, attachment_name, definition) if blob_or_blobs.empty?
  return append_blobs(attachment, blob_or_blobs) if append_only

  replace_blobs(attachment, blob_or_blobs)
end

.handle_has_one_attachment(attachment, blob_or_blobs, attachment_name:, definition:) ⇒ Object



106
107
108
109
110
111
112
113
# File 'lib/json_api/active_storage/deserialization.rb', line 106

def handle_has_one_attachment(attachment, blob_or_blobs, attachment_name:, definition:)
  if blob_or_blobs.present?
    attachment.purge if attachment.attached?
    attachment.attach(blob_or_blobs)
  elsif blob_or_blobs.nil?
    attachment.purge if purge_on_nil_enabled?(attachment_name, definition) && attachment.attached?
  end
end

.process_attachment(attrs, association_name, id_or_ids, singular:) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/json_api/active_storage/deserialization.rb', line 38

def process_attachment(attrs, association_name, id_or_ids, singular:)
  if singular
    blob = find_blob_by_signed_id(id_or_ids)
    attrs[association_name.to_s] = blob
  else
    blobs = Array(id_or_ids).map { |id| find_blob_by_signed_id(id) }
    attrs[association_name.to_s] = blobs
  end
end

.purge_on_nil_enabled?(attachment_name, definition) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
61
62
63
64
65
# File 'lib/json_api/active_storage/deserialization.rb', line 58

def purge_on_nil_enabled?(attachment_name, definition)
  return true unless definition

  relationship_def = find_relationship_definition(attachment_name, definition)
  return true unless relationship_def

  relationship_def[:options].fetch(:purge_on_nil, true)
end

.replace_blobs(attachment, blob_or_blobs) ⇒ Object



101
102
103
104
# File 'lib/json_api/active_storage/deserialization.rb', line 101

def replace_blobs(attachment, blob_or_blobs)
  attachment.purge if attachment.attached?
  attachment.attach(blob_or_blobs)
end