Ecto.Model.Schema
Defines a schema for a model.
A schema is a struct with associated metadata that is persisted to a repository. Every schema model is also a struct, that means that you work with models just like you would work with structs.
Example
defmodule User do
use Ecto.Model.Schema
schema "users" do
field :name, :string
field :age, :integer, default: 0
has_many :posts, Post
end
end
This module also automatically imports from/2
from Ecto.Query
as a convenience.
Schema defaults
When using the block syntax, the created model uses the default
of a primary key named :id
, of type :integer
. This can be
customized by passing primary_key: false
to schema:
schema "weather", primary_key: false do
...
end
Or by passing a tuple in the format {field, type, opts}
:
schema "weather", primary_key: {:custom_field, :string, []} do
...
end
Implicit defaults can be specified via the @schema_defaults
attribute.
This is useful if you want to use a different default primary key
through your entire application.
The supported options are:
primary_key
- eitherfalse
, or a{field, type, opts}
tupleforeign_key_type
- sets the type for any belongs_to associations.This can be overrided using the `:type` option to the `belongs_to` statement. Defaults to type `:integer`
Example
defmodule MyApp.Model do
defmacro __using__(_) do
quote do
@schema_defaults primary_key: {:uuid, :string, []},
foreign_key_type: :string
use Ecto.Model
end
end
end
defmodule MyApp.Post do
use MyApp.Model
schema "posts" do
has_many :comments, MyApp.Comment
end
end
defmodule MyApp.Comment do
use MyApp.Model
schema "comments" do
belongs_to :post, MyApp.Comment
end
end
Any models using MyApp.Model will get the
:uuid` field, with type
:string
as the primary key.
The belongs_to
association on MyApp.Comment
will also now require
that :post_id
be of :string
type to reference the :uuid
of a
MyApp.Post
model.
Setting Primary Keys with Schema Defaults
In the example above, the :uuid
primary key field needs to be
explicitly set by the developer before the Model can be inserted
or updated in a database.
To set a primary key, the developer must call the function
Ecto.Model.put_primary_key/2
.
Example:
uuid = "some_uuid"
# Don't do this
post = %MyApp.Post{uuid: uuid}
# Do this instead
post = Ecto.Model.put_primary_key(%MyApp.Post{}, uuid)
This must be done in order to ensure that any associations of the Model are appropriately updated.
Reflection
Any schema module will generate the __schema__
function that can be used for
runtime introspection of the schema.
__schema__(:source)
- Returns the source as given toschema/2
;__schema__(:field, field)
- Returns the options for the given field;__schema__(:field_type, field)
- Returns the type of the given field;__schema__(:field_names)
- Returns a list of all field names;__schema__(:associations)
- Returns a list of all association field names;__schema__(:association, field)
- Returns the given field’s associationreflection;
__schema__(:primary_key)
- Returns the field that is the primary key or`nil` if there is none;
__schema__(:allocate, values)
- Creates a new model struct from the givenfield values;
__schema__(:keywords, model)
- Return a keyword list of all non-virtualfields and their values;
Summary
belongs_to(name, queryable, opts \\ []) | Indicates a one-to-one association with another model, the current model
belongs to zero or one records of the other model. The other model
often has a |
field(name, type \\ :string, opts \\ []) | Defines a field on the model schema with given name and type, will also create
a struct field. If the type is |
has_many(name, queryable, opts \\ []) | Indicates a one-to-many association with another model, where the current
model has zero or more records of the other model. The other model often
has a |
has_one(name, queryable, opts \\ []) | Indicates a one-to-one association with another model, where the current model
has zero or one records of the other model. The other model often has a
|
schema(source, opts \\ [], block) | Defines a schema with a source name and field definitions |
Macros
Indicates a one-to-one association with another model, the current model
belongs to zero or one records of the other model. The other model
often has a has_one
or a has_many
field with the reverse association.
Compared to has_one
this association should be used where you would place
the foreign key on an SQL table.
Creates a virtual field called name
. The association can be accessed via
this field, see Ecto.Associations.BelongsTo
for more information. Check the
examples to see how to perform queries on the association and
Ecto.Query.join/3
for joins.
Options
:foreign_key
- Sets the foreign key field name, defaults to:`:"#{other_model}_id"`;
:references
- Sets the key on the other model to be used for theassociation, defaults to: `:id`;
:type
- Sets the type of:foreign_key
. Defaults to::integer
;
Examples
defmodule Comment do
schema "comments" do
belongs_to :post, Post
end
end
# The post can come preloaded on the comment record
[comment] = Repo.all(from(c in Comment, where: c.id == 42, preload: :post))
comment.post.get #=> %Post{...}
# Or via an association join
[comment] = Repo.all(from(c in Comment,
where: c.id == 42,
left_join: p in c.post,
select: assoc(c, p)))
comment.post.get #=> %Post{...}
Defines a field on the model schema with given name and type, will also create
a struct field. If the type is :virtual
it wont be persisted.
Options
:default
- Sets the default value on the schema and the struct;:primary_key
- Sets the field to be the primary key, the default primary key have to be overridden by setting its name tonil
;
Indicates a one-to-many association with another model, where the current
model has zero or more records of the other model. The other model often
has a belongs_to
field with the reverse association.
Creates a virtual field called name
. The association can be accessed via
this field, see Ecto.Associations.HasMany
for more information. See the
examples to see how to perform queries on the association and
Ecto.Query.join/3
for joins.
Options
:foreign_key
- Sets the foreign key, this should map to a field on theother model, defaults to: `:"#{model}_id"`;
:references
- Sets the key on the current model to be used for theassociation, defaults to the primary key on the model;
Examples
defmodule Post do
schema "posts" do
has_many :comments, Comment
end
end
# Get all comments for a given post
post = Repo.get(Post, 42)
comments = Repo.all(post.comments)
# The comments can come preloaded on the post struct
[post] = Repo.all(from(p in Post, where: p.id == 42, preload: :comments))
post.comments.all #=> [ %Comment{...}, ... ]
# Or via an association join
[post] = Repo.all(from(p in Post,
where: p.id == 42,
left_join: c in p.comments,
select: assoc(p, c)))
post.comments.all #=> [ %Comment{...}, ... ]
Indicates a one-to-one association with another model, where the current model
has zero or one records of the other model. The other model often has a
belongs_to
field with the reverse association.
Creates a virtual field called name
. The association can be accessed via
this field, see Ecto.Associations.HasOne
for more information. Check the
examples to see how to perform queries on the association and
Ecto.Query.join/3
for joins.
Options
:foreign_key
- Sets the foreign key, this should map to a field on theother model, defaults to: `:"#{model}_id"`;
:references
- Sets the key on the current model to be used for theassociation, defaults to the primary key on the model;
Examples
defmodule Post do
schema "posts" do
has_one :permalink, Permalink
end
end
# The permalink can come preloaded on the post record
[post] = Repo.all(from(p in Post, where: p.id == 42, preload: :permalink))
post.permalink.get #=> %Permalink{...}
# Or via an association join
[post] = Repo.all(from(p in Post,
where: p.id == 42,
left_join: pl in p.permalink,
select: assoc(p, pl)))
post.permalink.get #=> %Permalink{...}