Module: ActiveStorage::AwsRecord::Owner

Extended by:
ActiveSupport::Concern
Included in:
Blob, VariantRecord
Defined in:
lib/active_storage/aws_record/owner.rb

Overview

Make a greenfield aws-record model an Active Storage attachment owner: Attachable‘s contract glue plus an aws-record persistence implementation that runs Active Storage’s callback chains. Use this when the model has no persistence of its own; if it already defines save/destroy (versioning, events, search), include Attachable instead so this does not clobber them.

class Message
  include Aws::Record
  include ActiveStorage::AwsRecord::Owner
  string_attr :id, hash_key: true
  has_one_attached :avatar
  has_many_attached :images
end

Include Aws::Record before Owner (as above) so Owner‘s save/destroy sit above aws-record in the ancestor chain and their super reaches it.

Instance Method Summary collapse

Instance Method Details

#destroy(opts = {}) ⇒ Object Also known as: destroy!

Remove the backend record inside the destroy callbacks so Active Storage’s after_destroy cleanup sees persisted? == false, and only run :commit when the destroy actually happened. The delete! is guarded on persisted? so destroying a never-saved owner whose id collides with a stored row cannot delete the stored row.



68
69
70
71
72
73
74
75
76
77
78
# File 'lib/active_storage/aws_record/owner.rb', line 68

def destroy(opts = {})
  destroyed = false
  run_callbacks(:destroy) do
    if persisted?
      delete!(opts)
      destroyed = true
    end
  end
  run_callbacks(:commit) if destroyed
  destroyed
end

#save(opts = {}) ⇒ Object

Persist via aws-record inside the :save (then :commit) chains. super is aws-record’s terminal save (not its save!), so this never re-enters.



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/active_storage/aws_record/owner.rb', line 37

def save(opts = {})
  saved = false
  run_callbacks(:save) do
    stamp_physical_keys! if respond_to?(:stamp_physical_keys!)
    saved = super(opts)
    # A failed (invalid) save must not run after_save / flush attachments.
    throw :abort unless saved
    saved
  end
  run_callbacks(:commit) if saved
  saved
end

#save!(opts = {}) ⇒ Object

Bang variant. Delegates to #save (one callback run) rather than calling aws-record’s #save! — which delegates back to #save and would run the :save/:commit chains twice. A falsy #save is either a validation failure (surface the messages) or a before_save throw :abort.



54
55
56
57
58
59
60
61
# File 'lib/active_storage/aws_record/owner.rb', line 54

def save!(opts = {})
  return self if save(opts)

  message = errors.any? ? errors.full_messages.to_sentence : 'Save halted by a before_save callback'
  raise ActiveStorage::RecordNotSaved.new(message, self)
rescue Aws::Record::Errors::ConditionalWriteFailed => e
  raise ActiveStorage::RecordNotSaved.new(e.message, self)
end