This is a new major release of Ecto that removes previously deprecated features and introduces a series of improvements and features based on db_connection
.
Ecto has reimplemented the Ecto.Adapters.SQL.Sandbox
pool used for testing to use an ownership mechanism. This allows tests to safely run concurrently even when depending on the database. To use, declare sandbox as your pool in your repository configuration, as before:
pool: Ecto.Adapters.SQL.Sandbox
Now at the end of your test_helper.exs
, set the sandbox mode to :manual
, forcing connections to be automatically checked out:
Ecto.Adapters.SQL.Sandbox.mode(TestRepo, :manual)
And now checkout the connection in the setup
block of every test case that needs the database:
setup do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(TestRepo)
end
The previous sandbox API, which used begin_test_transaction
and restart_test_transaction
, is no longer supported.
Ecto now allows developers to insert multiple entries at once via Ecto.Repo.insert_all/3
:
Ecto.Repo.insert_all Post, [%{title: "foo"}, %{title: "bar"}]
Similar to update_all/3
, insert_all/3
is meant to be closer to the datastore and it won't automatically handle autogenerated fields like inserted_at
or updated_at
timestamps. insert_all/3
also adds to Ecto the ability to introduce entries to the database without an underlying Ecto.Schema
by simply giving a table name:
Ecto.Repo.insert_all "some_table", [%{hello: "foo"}, %{hello: "bar"}]
Ecto 2.0 supports many_to_many
associations:
defmodule Post do
use Ecto.Schema
schema "posts" do
many_to_many :tags, Tag, join_through: "posts_tags"
end
end
The join_through
option can be a string, representing a table that will have both post_id
and tag_id
columns, or a regular schema, like PostTag
, which would also handle primary keys and autogenerate fields. This is an improvement over has_many :through
as has_many :through
relationships are read-only, while many_to_many
supports also inserting, updating and deleting associated entries through changeset, as we will see next.
Ecto now supports belongs_to
and many_to_many
associations to be cast or changed via changesets, beyond has_one
, has_many
and embeds. Not only that, Ecto supports associations and embeds to be defined directly from the struct on insertion. For example, one can call:
Repo.insert! %Permalink{
url: "//root",
post: %Post{
title: "A permalink belongs to a post which we are inserting",
comments: [
%Comment{text: "child 1"},
%Comment{text: "child 2"},
]
}
}
This allows developers to easily insert a tree of structs into the database, be it when seeding data for production or during tests.
Finally, Ecto now allows putting existing records in changesets, and the proper changes will be reflected in both structs and the database. For example, you may retrieve the permalink above and associate it to another existing post:
permalink
|> Ecto.Changeset.change
|> Ecto.Changeset.put_assoc(:post, existing_post)
|> Repo.update!
Ecto.StaleModelError
has been renamed toEcto.StaleEntryError
- Array fields no longer default to an empty list
[]
. Previous behaviour can be achieved by passingdefault: []
to the field definition - Poolboy now expects
:pool_overflow
option instead of:max_overflow
Repo.insert/2
will now send only non-nil fields from the struct to the storage (in previous versions, all fields from the struct were sent to the database)Ecto.Pools.Poolboy
andEcto.Pools.SojournBroker
have been removed in favor ofDBConnection.Poolboy
andDBConnection.Sojourn
:timeout
inRepo.transaction
now affects the whole transaction block and not only the particular transaction queriesEcto.Adapters.SQL.begin_test_transaction
,Ecto.Adapters.SQL.restart_test_transaction
andEcto.Adapters.SQL.rollback_test_transaction
have been removed in favor of the new ownership basedEcto.Adapters.SQL.Sandbox
- Support expressions in map keys in
select
in queries. Example:from p in Post, select: %{p.title => p.visitors}
- Add support for partial indexes by specifying the
:where
option when onEcto.Migration.index/2
- Allow dynamic and atom fields to be specified on
group_by
anddistinct
- Ensure adapters work on native types, guaranteeing adapters compose better with custom types
- Allow the migration table name to be configured
- Add migration support for PostgreSQL exclusion constraints. Example:
create constraint(:sizes, :cannot_overlap, exclude: ~s|gist (int4range("min", "max", '[]') WITH &&)|)
- Add migration and changeset support for PostgreSQL check constraints. Example:
create constraint(@table.name, "positive_price", check: "price > 0")
andcheck_constraint(changeset, :description, name: :positive_price, message: "must be greater than zero")
- The
:required
option oncast_assoc
andcast_embed
will now taghas_many
andembeds_many
relationships as missing if they contain an empty list
- See the CHANGELOG.md in the v1.1 branch