PgORM::Base
Inherits PgORM::Validators < PgORM::Table < PgORM::Persistence < PgORM::Associations < ActiveModel::Callbacks < ActiveModel::Validation < ActiveModel::Model < DB::Mappable < DB::Serializable < YAML::Serializable < JSON::Serializable < Reference < Object
Constants
Constructors
Class methods
Returns all attribute keys.
Removes all records from the table using DELETE.
This is slower than truncate but respects foreign key constraints
and triggers any database-level triggers.
Example
User.clear # DELETE FROM users
Warning: This deletes all data! Use with caution.
Creates and attempts to save a new record to the database.
Returns the record regardless of whether it was saved successfully.
Check #persisted? to confirm if the save succeeded.
Example
user = User.create(name: "John", email: "john@example.com")
if user.persisted?
puts "User created with ID: #{user.id}"
else
puts "Failed to create user: #{user.errors}"
end
See also: #save
Creates and saves a new record to the database.
Raises an exception if validation fails or the record cannot be saved.
Example
user = User.create!(name: "John", email: "john@example.com")
# => #<User id: 1, name: "John", email: "john@example.com">
# Raises PgORM::Error::RecordInvalid if validation fails
User.create!(name: "") # => Error!
See also: #save!
Deletes multiple records by an array of IDs.
Does not load records into memory or run callbacks.
Use #destroy if you need callbacks.
Example
User.delete([1, 2, 3, 4, 5])
Deletes multiple records with composite primary keys.
Example
CompositeModel.delete([{key1: "a", key2: 1}, {key1: "b", key2: 2}])
Deletes one or more records by ID.
Does not load records into memory or run callbacks.
More efficient than destroy but doesn't trigger callbacks or update associations.
Example
# Delete single record
User.delete(1)
# Delete multiple records
User.delete(1, 2, 3, 4, 5)
Quickly removes all records from the table using TRUNCATE.
Much faster than clear for large tables, but:
- Requires table-level locks
- Resets auto-increment sequences
- Can cascade to related tables if
cascade: true
Example
# Truncate just this table
User.truncate(cascade: false)
# Truncate and cascade to related tables
User.truncate(cascade: true) # Also truncates related records
Warning: This deletes all data! Use with caution.
Updates one or more records by ID without loading them into memory.
This is more efficient than loading, modifying, and saving records. Does not run validations or callbacks.
Example
# Update single record
User.update(1, {name: "John Updated"})
User.update(1, name: "John Updated")
# Update multiple records by ID
User.update([1, 2, 3], {active: false})
# Update with composite primary key
CompositeModel.update({key1: "a", key2: 1}, {status: "active"})
Updates multiple records by an array of IDs.
Example
User.update([1, 2, 3], {active: false})
Updates multiple records with composite primary keys.
Example
CompositeModel.update([{key1: "a", key2: 1}, {key1: "b", key2: 2}], {status: "active"})
Updates records using keyword arguments.
Example
User.update(1, name: "John", active: true)
Instance methods
Generate code to apply default values
Assign to multiple attributes via HTTP::Params.
Assign to multiple attributes from a model object
Assign to multiple attributes.
Returns a Hash of all attribute values
Returns a NamedTuple of all attribute values.
Returns a Hash of all attributes that can be persisted.
Wrap a block with callbacks for the appropriate crud operation.
Defined once here rather than once per subclass, and reached through the
before_*/after_* methods rather than by expanding __before_* inline.
These methods yield, and Crystal cannot dispatch a yielding method through
a pointer -- it inlines the body at each call site. Defining them per
subclass therefore meant that a run_*_callbacks call on an abstract
receiver emitted one inlined copy per concrete subclass, each containing a
type-id dispatch chain for every self call in the block. Nesting two of
them (run_update_callbacks { run_save_callbacks { ... } }) made that
quadratic in the number of models.
With a single definition there is one inlined copy, and before_* /
after_* are ordinary non-yielding overrides that share one dispatch
wrapper.