Module: JSONAPI::ActiveStorage::Deserialization

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

Class Method Summary collapse

Class Method Details

.append_only_enabled?(attachment_name, definition) ⇒ Boolean

Returns:

  • (Boolean)


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

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
26
27
28
29
30
31
32
33
34
35
# 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 |attachment_name, blob_or_blobs|
    attachment = record.public_send(attachment_name)
    is_has_many = blob_or_blobs.is_a?(Array)
    append_only = is_has_many && append_only_enabled?(attachment_name, definition)

    if is_has_many
      handle_has_many_attachment(attachment, blob_or_blobs, append_only:,
                                                            attachment_name:, definition:)
    else
      handle_has_one_attachment(attachment, blob_or_blobs, attachment_name:,
                                                           definition:)
    end
  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



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

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



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

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_has_many_attachment(attachment, blob_or_blobs, append_only:, attachment_name:, definition:) ⇒ Object

Private helper methods



82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/json_api/active_storage/deserialization.rb', line 82

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

    attachment.purge if purge_on_nil_enabled?(attachment_name, definition) && attachment.attached?
  elsif append_only
    existing_blobs = attachment.attached? ? attachment.blobs.to_a : []
    attachment.attach(existing_blobs + blob_or_blobs)
  else
    attachment.purge if attachment.attached?
    attachment.attach(blob_or_blobs)
  end
end

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



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

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



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

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)


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

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