class Rotor::Model
The base class of a model: a row of a table, with typed accessors that
its table block generates when the program is compiled.
class DocUser < Rotor::Model
table "users" do
column :id, Int, primary: true
column :name, String
column :email, String, null: true
column :age, Int, default: 0
timestamps
end
end
u = DocUser.new(name: "Ann") # DocUser.new(name: 1) does not compile
u.name # => "Ann"
u.email # => nil
u.age # => 0
u.changed # => [:name]
v = u.with(email: "ann@example.com", age: 41)
v.age # => 41
u.age # => 0
DocUser.table_name # => "users"
DocUser.columns.map { |c| c.name } # => [:id, :name, :email, :age, :created_at, :updated_at]
A model is an immutable value, Shareable: with(col: value, ...)
gives a new one with those columns changed (each column an optional
keyword typed by it), which remembers the columns assigned since it
was made or loaded (changed): the columns an update writes. A
model's new takes the columns as with does (the same keywords,
all optional), starting from the columns' defaults, and remembers
those given as changed; load(values) makes one from a row's values,
unchanged. A model class cannot declare a var field (it is
Shareable), and does not write initialize: table generates its
constructors.
The columns are declared in one block because a class body's
statements run independently of each other (Quarz's docs/14 §2): no
statement sees what another generates, so the one table statement
is what knows every column, for columns and primary_key.
/home/runner/work/rotor/rotor/src/model.qz:48
Class methods
def self.defaults(info: Rotor::TableInfo) -> Hash[Symbol, Int | Float | String | Bool | Time | Bytes | Nil]
The columns' defaults.
static def self.table(name: String? = …, &block: Rotor::Schema.() -> Void) -> Void
Declares the model's table and its columns (Rotor::Schema), and
generates the typed accessors, the constructors (new of the
columns as optional keywords, and of a Checkpoint, which restore
makes), with, and the class's metadata: columns,
table_name (name, by default the class's name in snake_case,
plural), primary_key and associations. A class has one table
block.
def self.columns -> Array[Rotor::Column]
The columns, in order (generated by table).
def self.table_name -> String
The table's name (generated by table).
def self.primary_key -> Symbol?
The primary key's column, or nil for none (generated by table).
def self.associations -> Array[Rotor::Association]
The associations, in order (generated by table).
def self.table_info -> Rotor::TableInfo
The table's name, columns and primary key (generated by table).
def self.blank -> Self
A new model of this class: new, the columns' defaults set
(Rotor::Changeset.cast of a class).
def self.query -> Rotor::Query[Self]
Every row, as a query (Rotor::Query), to refine.
def self.preload(&spec: Quoted[shareable Self.() -> Object]) -> Rotor::Query[Self]
query.preload: every row, with the associations the block names
preloaded.
def self.where(&cond: Quoted[shareable Self.() -> Bool]) -> Rotor::Query[Self]
query.where: the rows for which the block is true.
def self.where(&cond: Quoted[shareable (Self) -> Bool]) -> Rotor::Query[Self]
query.where: the rows for which the block is true.
def self.filter(&cond: Quoted[shareable (Self) -> Bool]) -> Rotor::Query[Self]
query.filter.
def self.order(&key: Quoted[shareable Self.() -> Object]) -> Rotor::Query[Self]
query.order.
def self.order(&key: Quoted[shareable (Self) -> Object]) -> Rotor::Query[Self]
query.order.
def self.select[R](&f: Quoted[shareable Self.() -> R]) -> Rotor::Query[R]
query.select.
def self.select[R](&f: Quoted[shareable (Self) -> R]) -> Rotor::Query[R]
query.select.
def self.map[R](&f: Quoted[shareable (Self) -> R]) -> Rotor::Query[R]
query.map.
def self.count -> Rotor::Query[Int]
query.count.
def self.exists -> Rotor::Query[Bool]
query.exists.
def self.first -> Rotor::Query[Self]
query.first.
def self.limit(n: Int) -> Rotor::Query[Self]
query.limit(n).
def self.find_column(name: Symbol) -> Rotor::Column?
The column name, or nil for none.
def self.load(values: Hash[Symbol, Object?]) -> Self
A model of this class with the given values, unchanged: as read from a row. Each key must be a column, and each value of the column's type (or nil where the column admits NULL); the columns not given keep their defaults.
def self.load_partial(values: Hash[Symbol, Object?]) -> Self
A model with only the given columns loaded (a select fetched
them): reading another raises Rotor::NotLoadedError.
def self.rebuild(m: Rotor::Model) -> Self
A model of this class made of m's values (m one of this class):
how an association gives its models typed.
def self.value(v: Object?) -> Int | Float | String | Bool | Time | Bytes | Nil
v as a column's value (checked against its column before).
def self.own_table!(klass: Type[Object], owner: Type[Object], owner_name: String) -> Void
Raises unless klass is owner (named owner_name), the class
whose table generated the member called (the class itself, by
equal?, which no class can redefine, as == can be): a subclass
that inherits a table is refused at its first use (the members
with among them are its parent's).
def self.no_table_of(model: String) -> String
The message for a model without a table block.
def self.key_of(m: Rotor::Model, key: Symbol?) -> Int | Float | String | Bool | Time | Bytes | Nil
The value of m's column key (a key, primary or foreign), nil for
none or not set; raises Rotor::NotLoadedError when a query did not
fetch it.
def self.belonging[T <: Rotor::Model](target: Type[T], m: Rotor::Model, name: Symbol, fk: Symbol) -> T?
What a belongs_to getter gives (association).
Methods
def table_info -> Rotor::TableInfo
The table's name, columns and primary key, as the class's (generated
by table).
def restore(point: Rotor::Checkpoint) -> Self
A model of this class made of point.
def read(name: Symbol) -> Object?
The value of column name (nil for one not set that admits it).
def to_h -> Hash[Symbol, Int | Float | String | Bool | Time | Bytes | Nil]
The model's values by column, those set only: a column without a default that was never assigned is left out.
def changed -> Array[Symbol]
The columns assigned since the model was made or loaded, in the
order of their first assignment (one with's in the columns' order).
def changed? -> Bool
Whether a column was assigned since.
def keep_changes(names: Array[Symbol]) -> Self
The model with only the assignments of names kept (after the
others were saved).
def clear_changes -> Self
The model with the assignments forgotten: after it was saved.
def with_values(values: Hash[Symbol, Object?]) -> Self
A copy with the columns of values set, each checked against its
column's type, which remembers them as changed: what with does,
for code that names the columns at run time (the repository's
timestamps).
def loaded(values: Hash[Symbol, Object?], *, partial: Bool = …) -> Self
The model with the values read from a row (load), checked, and no
assignment; partial: when they are only those a query fetched
(load_partial), without the defaults.
def checkpoint -> Rotor::Checkpoint
What the model is made of.
def preloaded(name: Symbol) -> Array[Rotor::Model]?
The models preloaded for the association name, or nil when it was
not (Rotor::Repo#preload).
def with_preloaded(assocs: Hash[Symbol, Array[Rotor::Model]]) -> Self
The model with the associations of assocs preloaded (each by name,
the others kept).
def nest[T <: Rotor::Model](association: Rotor::HasMany[T], &: T.() -> Object) -> Object?
Preloading names associations: nest(posts) { comments } names
posts and, of each post, comments (Rotor::Repo#preload). Run
outside a preload, it gives nil.
def nest[T <: Rotor::Model](association: T?, &: T.() -> Object) -> Object?
Preloading names associations: nest(posts) { comments } names
posts and, of each post, comments (Rotor::Repo#preload). Run
outside a preload, it gives nil.
def inspect -> String
#<User id: 1, name: "Ann", password: **redacted**>: a column
declared redact: true hidden.
def to_s -> String
The value as a string, for puts and interpolation. For an instance of
a class, the class name in the form #<Point>; for an exception, its
message; for a data value or an enum variant, the default inspect.
It does not call an inspect the class defines.
from Object
def fetched?(name: Symbol) -> Bool
Whether the column name was fetched (all were, but for a model a
select loaded).