class Storage::Entry < ApplicationRecord belongs_to :account belongs_to :board, optional: true belongs_to :recordable, polymorphic: true, optional: true scope :pending, ->(last_entry_id) { where.not(id: ..last_entry_id) if last_entry_id } thread_mattr_accessor :recording, default: true def self.suppressing_recording(&block) original, self.recording = self.recording, false yield ensure self.recording = original end # Records may be destroyed (during cascading deletes) but .id still works. # Skip entirely if account is destroyed - no need to track storage for deleted accounts. # Skip materialize jobs for destroyed boards since there's nothing to update. def self.record(delta:, operation:, account:, board: nil, recordable: nil, blob: nil) return if delta.zero? return if account.destroyed? return unless recording entry = create! \ account_id: account.id, board_id: board&.id, recordable_type: recordable&.class&.name, recordable_id: recordable&.id, blob_id: blob&.id, delta: delta, operation: operation, user_id: Current.user&.id, request_id: Current.request_id account.materialize_storage_later board&.materialize_storage_later unless board&.destroyed? entry end end