module
PgORM::Persistence
Overview
Persistence module handles all database CRUD (Create, Read, Update, Delete) operations.
This module is automatically included in PgORM::Base and provides instance methods
for saving, updating, and deleting records, as well as class methods for bulk operations.
Lifecycle States
Records can be in one of three states:
- New: Not yet saved to database (
new_record? == true) - Persisted: Saved to database (
persisted? == true) - Destroyed: Deleted from database (
destroyed? == true)
Callbacks
Persistence operations trigger callbacks in this order:
- Create: before_create → before_save → after_save → after_create
- Update: before_update → before_save → after_save → after_update
- Destroy: before_destroy → after_destroy
Direct including types
Defined in:
pg-orm/persistence.crInstance Method Summary
-
#delete
Deletes the record from the database without callbacks.
-
#destroy
Destroys the record, running callbacks and updating associations.
-
#persisted?
Returns true if the record has been saved to the database and not destroyed.
-
#reload!
Reloads the record from the database, discarding any changes.
-
#save(**options)
Saves the record to the database.
-
#save!(**options)
Saves the record to the database, raising an exception on failure.
-
#update(**attributes)
Updates the record with new attributes and saves it.
-
#update!(**attributes)
Updates the record with new attributes and saves it, raising on failure.
-
#update_fields(**attributes)
Atomically updates specific fields without running callbacks or validations.
Instance Method Detail
Deletes the record from the database without callbacks.
This is faster than #destroy but:
- Does NOT run callbacks
- Does NOT update associations
- Does NOT wrap in a transaction
Use this for performance-critical deletions where you don't need the full destroy lifecycle.
Example
user = User.find(1)
user.delete # Direct DELETE query
Returns self (even if already destroyed or new).
Destroys the record, running callbacks and updating associations.
This is the "safe" way to delete records as it:
- Runs before_destroy and after_destroy callbacks
- Handles dependent associations (nullify, delete, destroy)
- Wraps everything in a transaction
Example
user = User.find(1)
user.destroy
user.destroyed? # => true
user.persisted? # => false
Returns self (even if already destroyed or new).
Returns true if the record has been saved to the database and not destroyed.
Example
user = User.new(name: "John")
user.persisted? # => false
user.save!
user.persisted? # => true
user.destroy
user.persisted? # => false
Reloads the record from the database, discarding any changes.
Useful for:
- Reverting unsaved changes
- Getting fresh data after external updates
- Clearing dirty tracking
Example
user = User.find(1)
user.name = "Changed"
user.reload! # Reverts to database value
user.changed? # => false
Raises
PgORM::Error::RecordNotSavedif record was never persistedPgORM::Error::RecordNotFoundif record no longer exists in database
Saves the record to the database.
For new records, performs an INSERT. For existing records, performs an UPDATE. Returns true if successful, false if validation fails.
Example
user = User.new(name: "John")
if user.save
puts "Saved! ID: #{user.id}"
else
puts "Failed: #{user.errors}"
end
# Update existing record
user.name = "Jane"
user.save # => true (if valid)
Callbacks
Triggers appropriate callbacks based on record state:
- New records: before_create, before_save, after_save, after_create
- Existing: before_update, before_save, after_save, after_update
Saves the record to the database, raising an exception on failure.
For new records, performs an INSERT. For existing records, performs an UPDATE. Only updates changed attributes (dirty tracking).
Example
user = User.new(name: "John")
user.save! # => #<User id: 1, name: "John">
user.name = "Jane"
user.save! # Only updates 'name' column
Raises
PgORM::Error::RecordNotSavedif record was destroyedPgORM::Error::RecordInvalidif validation failsPgORM::Error::RecordNotSavedif database operation fails
Updates the record with new attributes and saves it.
Returns true if successful, false if validation fails.
Example
user = User.find(1)
if user.update(name: "Jane", email: "[email protected]")
puts "Updated!"
else
puts "Failed: #{user.errors}"
end
Updates the record with new attributes and saves it, raising on failure.
Example
user = User.find(1)
user.update!(name: "Jane", email: "[email protected]")
Raises PgORM::Error::RecordInvalid if validation fails.
Atomically updates specific fields without running callbacks or validations.
This is faster than #update! but bypasses:
- Validations
- Callbacks (before_save, after_save, etc.)
- Dirty tracking (changes are cleared after update)
Use this for performance-critical updates where you don't need the full persistence lifecycle.
Example
user = User.find(1)
user.update_fields(last_login: Time.utc, login_count: 42)
# Direct UPDATE query, no callbacks
Raises Error::RecordNotSaved if called on a new record.