Model fields
This page provides a reference for all the available field options and field types that can be used when defining models.
Common field options
The following field options can be used for all the available field types when declaring model fields using the field
macro.
blank
The blank
argument allows to define whether a field is allowed to receive blank values from a validation perspective. The fields with blank: false
that receive blank values will make their associated model record validation fail. The default value for this argument is false
.
db_column
The db_column
argument can be used to specify the name of the column corresponding to the field at the database level. Unless specified, the database column name will correspond to the field name.
default
The default
argument allows to define a default value for a given field. The default value for this argument is nil
.
index
The index
argument can be used to specify that a database index must be created for the corresponding column. The default value for this argument is false
.
primary_key
The primary_key
argument can be used to specify that a field corresponds to the primary key of the considered model table. The default value for this argument is false
.
null
The null
argument allows to define whether a field is allowed to store NULL
values in the database. The default value for this argument is false
.
unique
The unique
argument allows to define that values for a specific field must be unique throughout the associated table. The default value for this argument is false
.
Field types
big_int
A big_int
field allows persisting 64-bit integers. In addition to the common field options, such fields support the following arguments:
auto
The auto
argument auto-increment for the considered database column. Defaults to false
.
This argument will be used mainly when defining integer IDs that automatically increment:
class MyModel < Marten::Model
field :id, :big_int, primary_key: true, auto: true
# ...
end
bool
A bool
field allows persisting booleans.
date
A date
field allows persisting date values, which map to Time
objects in Crystal. In addition to the common field options, such fields support the following arguments:
auto_now
The auto_now
argument allows ensuring that the corresponding field value is automatically set to the current time every time a record is saved. This provides a convenient way to define updated_at
fields. Defaults to false
.
auto_now_add
The auto_now_add
argument allows ensuring that the corresponding field value is automatically set to the current time every time a record is created. This provides a convenient way to define created_at
fields. Defaults to false
.
date_time
A date_time
field allows persisting date-time values, which map to Time
objects in Crystal. In addition to the common field options, such fields support the following arguments:
auto_now
The auto_now
argument allows ensuring that the corresponding field value is automatically set to the current time every time a record is saved. This provides a convenient way to define updated_at
fields. Defaults to false
.
auto_now_add
The auto_now_add
argument allows ensuring that the corresponding field value is automatically set to the current time every time a record is created. This provides a convenient way to define created_at
fields. Defaults to false
.
duration
A duration
field allows persisting duration values, which map to Time::Span
objects in Crystal. duration
fields are persisted as big integer values (number of nanoseconds) at the database level.
email
An email
field allows to persist valid email addresses. In addition to the common field options, such fields support the following arguments:
max_size
The max_size
argument is optional and defaults to 254 characters (in accordance with RFCs 3696 and 5321). It allows to specify the maximum size of the persisted email addresses. This maximum size is used for the corresponding column definition and when it comes to validating field values.
enum
An enum
field allows persisting the value of an Enum
. When defining enum
fields, it's necessary to specify a values
argument that matches the actual enum:
enum Category
NEWS
BLOG
end
class Article < Marten::Model
field :id, :big_int, primary_key: true, auto: true
field :category, :enum, values: Category
end
article = Article.last!
article.category # => Category::BLOG
The way enums are handled at the database level depends on the database backend being used. Indeed, an ENUM type is used for MySQL databases while column checks are used for SQLite and PostgreSQL databases.
In addition to the common field options, such fields support the following arguments:
values
The values
argument is required and allows to specify the actual enum class that should be used for the field. It is worth mentioning that the configured enum will impact the values allowed for the corresponding column at the database level.
file
A file
field allows persisting the reference to an uploaded file.
file
fields can't be configured as primary keys.
storage
This optional argument can be used to configure the storage that will be used to persist the actual files. It defaults to the media files storage (configured via the media_files.storage
setting), but can be overridden on a per-field basis if needed:
my_storage = Marten::Core::Storage::FileSystem.new(root: "files", base_url: "/files/")
class Attachment < Marten::Model
field :id, :big_int, primary_key: true, auto: true
field :uploaded_file, :file, storage: my_storage
end
Please refer to Managing files for more details on how to manage uploaded files and the associated storages.
upload_to
This optional argument can be used to configure where the uploaded files are persisted in the storage. It defaults to an empty string and can be set to either a string or a proc.
If set to a string, it allows to define in which directory of the underlying storage files will be persisted:
class Attachment < Marten::Model
field :id, :big_int, primary_key: true, auto: true
field :uploaded_file, :file, upload_to: "foo/bar"
end
If set to a proc, it allows to customize the logic allowing to generate the resulting path and filename:
class Attachment < Marten::Model
field :id, :big_int, primary_key: true, auto: true
field :uploaded_file, :file, upload_to: ->(filename : String) { File.join("files/uploads", filename) }
end
float
A float
field allows persisting floating point numbers (Float64
objects).
int
An int
field allows persisting 32-bit integers. In addition to the common field options, such fields support the following arguments:
auto
The auto
argument auto-increment for the considered database column. Defaults to false
.
This argument will be used mainly when defining integer IDs that automatically increment:
class MyModel < Marten::Model
field :id, :int, primary_key: true, auto: true
# ...
end
json
A json
field allows persisting JSON values to the database.
JSON values are automatically parsed from the underlying database column and exposed as a JSON::Any
object (or nil
if no values are available) by default in Crystal:
class MyModel < Marten::Model
# Other fields...
field :metadata, :json
end
MyModel.last!.metadata # => JSON::Any object
Additionally, it is also possible to specify a serializable
option in order to specify a class that makes use of JSON::Serializable
. When doing so, the parsing of the JSON values will result in the initialization of the corresponding serializable objects:
class MySerializable
include JSON::Serializable
property a : Int32 | Nil
property b : String | Nil
end
class MyModel < Marten::Model
# Other fields...
field :metadata, :json, serializable: MySerializable
end
MyModel.last!.metadata # => MySerializable object
It should be noted that json
fields are mapped to:
jsonb
columns in PostgreSQL databasestext
columns in MySQL databasestext
columns in SQLite databases
serializable
The serializable
arguments allows to specify that a class making use of JSON::Serializable
should be used in order to parse the JSON values for the model field at hand. When specifying a serializable
class, the values returned for the considered model fields will be instances of that class instead of JSON::Any
objects.
slug
A slug
field allows to persist valid slug values (ie. strings that can only include characters, numbers, dashes, and underscores). In addition to the common field options, such fields support the following arguments:
Since slug fields are usually used to query records, they are indexed by default. You can use the index
option (index: false
) to disable auto-indexing.
max_size
The max_size
argument is optional and defaults to 50 characters. It allows to specify the maximum size of the persisted email addresses. This maximum size is used for the corresponding column definition and when it comes to validate field values.
slugify
The slugify
argument allows specifying the field from which the slug should be generated. This is useful when you want the slug to be automatically derived from another field.
class Article < Marten::Model
field :title, :string
field :slug, :slug, slugify: :title
end
article = Article.create!(title: "My Article")
article.slug # => "my-article"
When an Article
object is saved, the slug field will automatically generate a slug based on the title field if no custom slug is provided.
The slugification functionality also transforms Unicode characters and symbols. When filtering a model by the query parameter, it may be necessary to decode the slug parameter first, because although the browser may show you the unicode characters, it will send the encoded characters in the HTTP request:
class ArticleDetailsHandler < Marten::Handler
def get
article = Article.get(slug: URI.decode(params[:slug].to_s))
# …
end
end
string
A string
field allows to persist small or medium string values. In addition to the common field options, such fields support the following arguments:
max_size
The max_size
argument is required and allows to specify the maximum size of the persisted string. This maximum size is used for the corresponding column definition and when it comes to validate field values.
min_size
The min_size
argument allows defining the minimum size allowed for the persisted string. The default value for this argument is nil
, which means that the minimum size is not validated by default.
text
A text
field allows to persist large text values. In addition to the common field options, such fields support the following arguments:
max_size
The max_size
argument allows to specify the maximum size of the persisted string. This maximum size is used when it comes to validate field values. Defaults to nil
.
url
A url
field allows persisting valid URL addresses. In addition to the common field options, such fields support the following arguments:
max_size
The max_size
argument is optional and defaults to 200 characters. It allows to specify the maximum size of the persisted URLs. This maximum size is used for the corresponding column definition and when it comes to validate field values.
uuid
A uuid
field allows persisting Universally Unique IDentifiers (UUID
objects).
Relationship field types
many_to_many
A many_to_many
field allows to define a many-to-many relationship. This special field type requires the use of a special to
argument in order to specify the model class to which the current model is related.
For example, an Article
model could have a many-to-many field towards a Tag
model. In such case, an Article
record could have many associated Tag
records, and every Tag
records could be associated to many Article
records as well:
class Tag < Marten::Model
# ...
end
class Article < Marten::Model
# ...
field :tags, :many_to_many, to: Tag
end
In addition to the common field options, such fields support the following arguments:
to
The to
argument is required and allows to specify the model class that is related to the model where the many_to_many
field is defined.
related
The related
argument allows defining the name of the reverse (or backward) relation on the targetted model. If we consider the previous example, it could be possible to define an articles
backward relation in order to let Tag
records expose their related Article
records:
class Tag < Marten::Model
# ...
end
class Article < Marten::Model
# ...
field :tags, :many_to_many, to: Tag, related: :articles
end
When the related
argument is used, a method will be automatically created on the targetted model by using the chosen argument's value. For example, this means that all the Article
records using a specific Tag
record could be accessed through the use of the Tag#articles
method in the previous snippet.
The default value is nil
, which means that no reverse relation is defined on the targetted model by default.
many_to_one
A many_to_one
field allows defining a many-to-one relationship. This special field type requires the use of a special to
argument in order to specify the model class to which the current model is related.
For example, an Article
model could have a many-to-one field towards an Author
model. In such case, an Article
record would only have one associated Author
record, but every Author
record could be associated to many Article
records:
class Author < Marten::Model
# ...
end
class Article < Marten::Model
# ...
field :author, :many_to_one, to: Author
end
In addition to the common field options, such fields support the following arguments:
to
The to
argument is required and allows to specify the model class that is related to the model where the many_to_one
field is defined.
related
The related
argument allows defining the name of the reverse (or backward) relation on the targetted model. If we consider the previous example, it could be possible to define an articles
backward relation in order to let Author
records expose their related Article
records:
class Author < Marten::Model
# ...
end
class Article < Marten::Model
# ...
field :author, :many_to_one, to: Author, related: :articles
end
When the related
argument is used, a method will be automatically created on the targetted model by using the chosen argument's value. For example, this means that all the Article
records associated with a specific Author
record could be accessed through the use of the Author#articles
method in the previous snippet.
The default value is nil
, which means that no reverse relation is defined on the targetted model by default.
on_delete
The on_delete
argument allows to specify the deletion strategy to adopt when a related record (one that is targeted by the many_to_one
field) is deleted. The following strategies can be specified (as symbols):
:do_nothing
: is the default strategy. With this strategy, Marten won't do anything to ensure that records referencing the record being deleted are deleted or updated. If the database enforces referential integrity (which will be the case for foreign key fields), this means that deleting a record could result in database errors.:cascade
: this strategy can be used to perform cascade deletions. When deleting a record, Marten will try to first destroy the other records that reference the object being deleted.:protect
: this strategy allows to explicitly prevent the deletion of records if they are referenced by other records. This means that attempting to delete a "protected" record will result in aMarten::DB::Errors::ProtectedRecord
error.:set_null
: this strategy will set the reference column tonull
when the related record is deleted.
one_to_one
A one_to_one
field allows defining a one-to-one relationship. This special field type requires the use of a special to
argument in order to specify the model class to which the current model is related.
For example, a User
model could have a one-to-one field towards a Profile
model. In such case, the User
model could only have one associated Profile
record, and the reverse would be true as well (a Profile
record could only have one associated User
record). In fact, a one-to-one field is really similar to a many-to-one field, but with an additional unicity constraint:
class Profile < Marten::Model
# ...
end
class User < Marten::Model
# ...
field :profile, :one_to_one, to: Profile
end
In addition to the common field options, such fields support the following arguments:
to
The to
argument is required and allows to specify the model class that is related to the model where the one_to_one
field is defined.
related
The related
argument allows defining the name of the reverse (or backward) relation on the targetted model. If we consider the previous example, it could be possible to define a user
backward relation in order to let Profile
records expose their related User
record:
class Profile < Marten::Model
# ...
end
class User < Marten::Model
# ...
field :profile, :one_to_one, to: Profile, related: :user
end
When the related
argument is used, a method will be automatically created on the targetted model by using the chosen argument's value. For example, this means that the User
record associated with a specific Profile
record could be accessed through the use of the Profile#user
method in the previous snippet.
The default value is nil
, which means that no reverse relation is defined on the targetted model by default.