Recording
Record operation executions to a database table for auditing, debugging, or analytics. Supports ActiveRecord and Mongoid.
Setup
Create a model and table for storing records:
# migration
create_table :operation_records do |t|
t.string :name, null: false # operation class name
t.jsonb :params, default: {} # operation properties
t.jsonb :response # return value
t.string :status # pending/running/done/failed
t.string :error # error code on failure
t.datetime :performed_at # execution timestamp
t.timestamps
end# app/models/operation_record.rb
class OperationRecord < ApplicationRecord
endThen configure dexkit:
# config/initializers/dex.rb
Dex.configure do |config|
config.record_class = OperationRecord
endAll columns except name are optional – dexkit only writes to columns that exist on the model. Add what you need, leave out what you don't.
What gets recorded
By default, both params and the response are recorded:
class CreateUser < Dex::Operation
prop :email, String
prop :name, String
def perform
User.create!(email: email, name: name)
end
end
CreateUser.call(email: "alice@example.com", name: "Alice")
# OperationRecord:
# name: "CreateUser"
# params: { "email" => "alice@example.com", "name" => "Alice" }
# response: { "id" => 1, "email" => "alice@example.com", ... }
# status: "done"
# performed_at: 2024-01-15 10:30:00Ref types (_Ref(User)) serialize as IDs in both params and response, keeping records clean and compact.
Controlling what's recorded
class SensitiveOperation < Dex::Operation
record false # disable recording entirely
end
class LargeResponse < Dex::Operation
record response: false # record params only
end
class AuditTrail < Dex::Operation
record params: false # record response only
endSuccess type and response
When success Type is declared, dexkit serializes the response intelligently:
class FindUser < Dex::Operation
success _Ref(User)
def perform
User.find(user_id)
end
end
# response is stored as just the user ID, not the full serialized objectFor other return types, the response is stored as-is (Hash), or wrapped in { value: ... } for scalar values.
Async integration
When combined with Async, recording provides status tracking across the operation's lifecycle. See the Async page for details.
Anonymous operations
Operations without a class name (anonymous classes) are not recorded, since there's no meaningful name to store.