Ecto.Schema

Parsed documentation:
View on GitHub
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.Schema

      schema "users" do
        field :name, :string
        field :age, :integer, default: 0
        has_many :posts, Post
      end
    end

By default, a schema will generate both a primary key named `id`
of type `:integer` and `belongs_to` associations will generate
foreign keys of type `:integer` too. Those setting can be configured
below.

## Schema attributes

The schema supports some attributes to be set before hand,
configuring the defined schema.

Those attributes are:

  * `@primary_key` - configures the schema primary key. It expects
    a tuple with the primary key name, type and options. Defaults
    to `{:id, :integer, []}`. When set to false, does not define
    a primary key in the model;

  * `@foreign_key_type` - configures the default foreign key type
    used by `belongs_to` associations. Defaults to `:integer`;

  * `@timestamps_type` - configures the default timestamps type
    used by `timestamps`. Defaults to `:datetime`;

  * `@derive` - the same as `@derive` available in `Kernel.defstruct/1`
    as the schema defines a struct behind the scenes;

The advantage of defining configure the schema via those attributes
is that they can be set with a macro to configure application wide
defaults. For example, if you would like to use `uuid`'s in all of
your application models, you can do:

    # Define a module to be used as base
    defmodule MyApp.Model do
      defmacro __using__(_) do
        quote do
          use Ecto.Model
          @primary_key {:id, :uuid, []}
          @foreign_key_type :uuid
        end
      end
    end

    # Now use MyApp.Model to define new models
    defmodule MyApp.Comment do
      use MyApp.Model

      schema "comments" do
        belongs_to :post, MyApp.Post
      end
    end

Any models using `MyApp.Model` will get the `:id` field with type
`:uuid` as primary key.

The `belongs_to` association on `MyApp.Comment` will also define
a `:post_id` field with `:uuid` type that references the `:id` of
the `MyApp.Post` model.

## Types and casting

When defining the schema, types need to be given. Those types are
specific to Ecto and must be one of:

Ecto type               | Elixir type             | Literal syntax in query
:---------------------- | :---------------------- | :---------------------
`:integer`              | `integer`               | 1, 2, 3
`:float`                | `float`                 | 1.0, 2.0, 3.0
`:boolean`              | `boolean`               | true, false
`:string`               | UTF-8 encoded `binary`  | "hello"
`:binary`               | `binary`                | `<<int, int, int, ...>>`
`:uuid`                 | 16 byte `binary`        | `uuid(binary_or_string)`
`{:array, inner_type}`  | `list`                  | `[value, value, value, ...]`
`:decimal`              | [`Decimal`](https://github.com/ericmj/decimal)
`:datetime`             | `%Ecto.DateTime{}`
`:date`                 | `%Ecto.Date{}`
`:time`                 | `%Ecto.Time{}`

Models can also have virtual fields by passing the `virtual: true`
option. These fields are not persisted to the database and can
optionally not be type checked by declaring type `:any`.

When directly manipulating the struct, it is the responsibility of
the developer to ensure the field values have the proper type. For
example, you can create a weather struct with an invalid value
for `temp_lo`:

    iex> weather = %Weather{temp_lo: "0"}
    iex> weather.temp_lo
    "0"

However, if you attempt to persist the struct above, an error will
be raised since Ecto validates the types when building the query.

Therefore, when working and manipulating external data, it is
recommended the usage of `Ecto.Changeset`'s that are able to filter
and properly cast external data. In fact, `Ecto.Changeset` and custom
types provide a powerful combination to extend Ecto types and queries.

## Custom types

Besides the types mentioned above, Ecto allows custom types to be
defined. A custom type is a module that implements the `Ecto.Type`
behaviour. Read the `Ecto.Type` documentation for more information
on how to implement them.

## 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 to `schema/2`;
* `__schema__(:primary_key)` - Returns the field that is the primary
  key or `nil` if there is none;

* `__schema__(:fields)` - Returns a list of all non-virtual field names;
* `__schema__(:field, field)` - Returns the type of the given non-virtual field;

* `__schema__(:associations)` - Returns a list of all association field names;
* `__schema__(:association, assoc)` - Returns the association reflection of the given assoc;

* `__schema__(:read_after_writes)` - Non-virtual fields that must be read back
  from the database after every write (insert or update);

* `__schema__(:load, struct \\ __struct__(), fields_or_idx, values)` - Loads a
  new model struct from a tuple of non-virtual field values starting at the given
  index or defined by the given fields;

Furthermore, both `__struct__` and `__changeset__` functions are
defined so structs and changeset functionalities are available.
No suggestions.
Please help! Open an issue on GitHub if this assessment is incorrect.