View Source SwissSchema behaviour (swiss_schema v0.6.0)
SwissSchema
is a query toolkit for Ecto schemas. It makes it easy to manipulate data using Ecto schemas by implementing relevant Ecto.Repo Query API and Schema API functions, pre-configured to work specifically with the given Ecto schema.
Setup
Add swiss_schema
as a dependency in mix.exs
:
def deps do
[
# ...
{:swiss_schema, "~> 0.6"}
]
end
Then, use SwissSchema
in your Ecto schemas:
# lib/my_app/accounts/user.ex
defmodule MyApp.Accounts.User do
use Ecto.Schema
use SwissSchema, repo: MyApp.Repo
def changeset(%__MODULE__{} = user, params) do
# Set up your schema's default changeset here
end
end
That's it, you should be good to go.
Usage
After setting up SwissSchema in your Ecto schema, there isn't much else to do. Just use the available functions now available in your own schema module:
iex> alias MyApp.Accounts.User
iex> User.all()
[]
iex> User.create(%{name: "John Smith", email: "john@smiths.net"})
{:ok, %User%{name: "John Smith", ...}}
iex> User.all()
[%User%{name: "John Smith", ...}]
SwissSchema
functions tries to mimic the Ecto.Repo's Query and Repo APIs by acting as a thin, pre-configured interface for Ecto.Repo callbacks.
Note
To keep examples simple and short, we use the example module above,
MyApp.Accounts.User
, through the documentation. So, when reading the docs for SwissSchema functions, assume the following alias was previously set up:alias MyApp.Accounts.User
So,
MyApp.Accounts.User
will be referred to asUser
.
Summary
Ecto.Repo Query API
Calculate the given aggregation.
Calculate the given aggregate
over the given field
.
Fetches all entries from the respective data store.
Deletes all entries.
Fetches an entry by the primary key.
Similar to get/2
but raises Ecto.NoResultsError
if no entry was found.
Fetches a single entry by using a keyword list of clauses.
Similar to get_by/2
but raises Ecto.NoResultsError
if no entry is found, or Ecto.MultipleResultsError
if multiple entries are found.
Returns a lazy enumerable that emits all entries from the data store.
Updates all entries matching the given query with the given values.
Ecto.Repo Schema API
Deletes an entry using its primary key.
Same as delete/2
but returns the entry, or raises.
Inserts a new entry.
Same as insert/2
but returns the struct or raises if the changeset is invalid.
Inserts all entries into the repository.
Inserts or updates a changeset depending on whether the struct is persisted or not.
Same as insert_or_update/2
but returns the struct or raises if parameters are invalid.
SwissSchema API
Defines the default changeset function.
Creates a new struct.
Same as create/2
but returns the struct or raises if parameters are invalid.
Updates a struct.
Same as update/3
but returns the struct or raises if parameters are invalid.
Ecto.Repo Query API
Calculate the given aggregation.
Examples
# Returns the number of users
User.aggregate(:count)
# Set a timeout of 60s
User.aggregate(:count, timeout: 60_000)
See Ecto's
aggregate/3
for extensive info.
@callback aggregate( type :: :avg | :count | :max | :min | :sum, field :: atom(), opts :: Keyword.t() ) :: term() | nil
Calculate the given aggregate
over the given field
.
Examples
# Returns the sum of the number of visits for every user
User.aggregate(:sum, :visits)
# Returns the average number of user visits
User.aggregate(:avg, :visits)
See Ecto's
aggregate/4
for extensive info.
@callback all(opts :: Keyword.t()) :: [Ecto.Schema.t() | term()]
Fetches all entries from the respective data store.
Examples
# Fetch all users
User.all()
See Ecto's
all/2
for extensive info.
@callback delete_all(opts :: Keyword.t()) :: {non_neg_integer(), nil | [term()]}
Deletes all entries.
It returns a two-values tuple: the number of entries deleted, and nil
.
Examples
User.delete_all()
See Ecto's
delete_all/2
for extensive info.
@callback get( id :: term(), opts :: Keyword.t() ) :: {:ok, Ecto.Schema.t()} | {:ok, term()} | {:error, :not_found}
Fetches an entry by the primary key.
It returns {:ok, entry}
if the entry is found, or {:error, :not_found}
otherwise.
Examples
iex> User.get(1)
{:ok, %User{}}
iex> User.get(1234567890)
{:error, :not_found}
See Ecto's
get/3
for extensive info.
@callback get!( id :: term(), opts :: Keyword.t() ) :: Ecto.Schema.t() | term()
Similar to get/2
but raises Ecto.NoResultsError
if no entry was found.
Examples
iex> User.get!(1)
%User{}
iex> User.get!(1234567890)
** (Ecto.NoResultsError) expected at least one result but got none in query
See Ecto's
get!/3
for extensive info.
@callback get_by( clauses :: Keyword.t() | map(), opts :: Keyword.t() ) :: {:ok, Ecto.Schema.t()} | {:ok, term()} | {:error, :not_found}
Fetches a single entry by using a keyword list of clauses.
It returns a single matching entry as {:ok, entry}
, or {:error, :not_found}
when none is found.
Examples
iex> User.get_by(email: "john@smiths.net")
%User{}
See Ecto's
get_by/3
for extensive info.
@callback get_by!( clauses :: Keyword.t() | map(), opts :: Keyword.t() ) :: Ecto.Schema.t() | term()
Similar to get_by/2
but raises Ecto.NoResultsError
if no entry is found, or Ecto.MultipleResultsError
if multiple entries are found.
Examples
iex> User.get_by!(email: "john@smiths.net")
%User{}
iex> User.get_by!(email: "nobody@localhost")
** (Ecto.NoResultsError)
iex> User.get_by!(first_name: "John")
** (Ecto.MultipleResultsError)
See Ecto's
get_by!/3
for extensive info.
Returns a lazy enumerable that emits all entries from the data store.
See Ecto's
stream/2
for extensive info.
@callback update_all( updates :: Keyword.t(), opts :: Keyword.t() ) :: {non_neg_integer(), nil | [term()]}
Updates all entries matching the given query with the given values.
Examples
iex> User.update_all(set: [is_active: false])
iex> User.update_all(inc: [age: 1])
See Ecto's
update_all/3
for extensive info.
Ecto.Repo Schema API
@callback delete( struct :: Ecto.Schema.t(), opts :: Keyword.t() ) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
Deletes an entry using its primary key.
It returns {:ok, struct}
if the entry has been successfully deleted or {:error, changeset}
if there was a validation or a known constraint error.
Examples
user = User.get!(42)
case User.delete user do
{:ok, user} -> # Deleted with success
{:error, changeset} -> # Something went wrong
end
See Ecto's
delete/2
for extensive info.
@callback delete!( struct :: Ecto.Schema.t(), opts :: Keyword.t() ) :: Ecto.Schema.t()
Same as delete/2
but returns the entry, or raises.
Examples
user = User.get!(42)
User.delete user do
{:ok, user} -> # Deleted with success
{:error, changeset} -> # Something went wrong
end
See Ecto's
delete!/2
for extensive info.
@callback insert( params :: %{required(atom()) => term()}, opts :: Keyword.t() ) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
Inserts a new entry.
Accepts a map with key-values matching respective schema fields.
It returns {:ok, struct}
if the entry has been successfully inserted, or
{:error, %Ecto.Changeset{}}
if there is a validation or a known constraint error.
Examples
A typical example is calling insert/2
with a map and acting on the
return value:
case User.insert(%{name: "John S.", email: "john@smiths.net"}) do
{:ok, user} -> # Inserted with success
{:error, changeset} -> # Something went wrong
end
See Ecto's
insert/2
for extensive info.
@callback insert!( params :: %{required(atom()) => term()}, opts :: Keyword.t() ) :: Ecto.Schema.t()
Same as insert/2
but returns the struct or raises if the changeset is invalid.
@callback insert_all( entries :: [%{required(atom()) => term()}] | Keyword.t(), opts :: Keyword.t() ) :: {non_neg_integer(), nil | [term()]}
Inserts all entries into the repository.
Examples
User.insert_all([ [name: "John S."], [name: "Jane S."] ])
User.insert_all([ %{name: "John S."}, %{name: "Jane S."} ])
See Ecto's
insert_all/3
for extensive info.
@callback insert_or_update( changeset :: Ecto.Changeset.t(), opts :: Keyword.t() ) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
Inserts or updates a changeset depending on whether the struct is persisted or not.
Examples
iex> User.changeset(%User{}, %{name: "John S.", email: "john@smiths.net"})
|> User.insert_or_update()
{:ok, %User{}}
User.get_by!(email: "john@smiths.net")
|> User.changeset(%{email: "john.s@smiths.net"})
|> User.insert_or_update()
See Ecto's
insert_or_update/2
for extensive info.
@callback insert_or_update!( changeset :: Ecto.Changeset.t(), opts :: Keyword.t() ) :: Ecto.Schema.t()
Same as insert_or_update/2
but returns the struct or raises if parameters are invalid.
See Ecto's
insert_or_update!/2
for extensive info.
SwissSchema API
@callback changeset( struct :: Ecto.Schema.t(), params :: %{required(atom()) => term()} ) :: Ecto.Changeset.t()
Defines the default changeset function.
This callback is used by database-touching functions to validate changes.
Examples
User.changeset(%User{}, %{name: "John"})
iex> %Ecto.Changeset{valid?: true}
See Ecto's
Ecto.Changeset
for extensive info.
@callback create( params :: %{required(atom()) => term()}, opts :: Keyword.t() ) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
Creates a new struct.
create/2
accepts a key-value map, validates it against the schema's changeset/2
, and inserts into the repository if the validation succeeds.
Examples
# Returns an :ok tuple with valid params
{:ok, user} = User.create(%{name: "John S.", email: "john@smiths.net"})
# Returns an :error tuple with invalid params
{:error, %Ecto.Changeset{...}} = User.create(%{name: 123, email: "john"})
@callback create!( params :: %{required(atom()) => term()}, opts :: Keyword.t() ) :: Ecto.Schema.t()
Same as create/2
but returns the struct or raises if parameters are invalid.
@callback update( struct :: Ecto.Schema.t(), params :: %{required(atom()) => term()}, opts :: Keyword.t() ) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
Updates a struct.
Examples
iex> User.get_by!(email: "john@smiths.net")
|> User.update(%{email: "john.s@smiths.net"})
{:ok, %User{}}
See Ecto's
update/2
for extensive info.
@callback update!( struct :: Ecto.Schema.t(), params :: %{required(atom()) => term()}, opts :: Keyword.t() ) :: Ecto.Schema.t()
Same as update/3
but returns the struct or raises if parameters are invalid.
Examples
iex> User.get_by!(email: "john@smiths.net")
|> User.update!(%{email: "john.s@smiths.net"})
%User{}
See Ecto's
update!/2
for extensive info.