View Source EctoShorts.Actions (ecto_shorts v2.4.0)

Actions for CRUD in ecto, these can be used by all schemas/queries

Generally we can define our contexts to be very reusable by creating them to look something like this:

defmodule MyApp.Accounts do
  alias EctoShorts.Actions
  alias MyApp.Accounts.User

  def all_users(params), do: Actions.all(User, params)
  def find_user(params), do: Actions.find(User, params)
end

We're then able to use this context with all filters that are supported by EctoShorts.CommonFilters without having to create new queries

def do_something do
  MyApp.Accounts.all_user(%{
    first_name: %{ilike: "john"},
    age: %{gte: 18},
    priority_level: 5,
    address: %{country: "Canada"}
  })
end

You can read more on reusable ecto code here

Supporting multiple Repos

To support multiple repos, what we can do is pass arguments to the last parameter of most EctoShorts.Actions calls

Example

defmodule MyApp.Accounts do
  alias EctoShorts.Actions
  alias MyApp.Accounts.User

  @repo [repo: MyApp.Repo.Replica1]

  def all_users(params), do: Actions.all(User, params, @repo)
  def find_user(params), do: Actions.find(User, params, @repo)
end

Summary

Functions

Gets a collection of schemas from the database

Gets a collection of schemas from the database but allows for a filter or an options list.

Similar to all/2 but can also accept a keyword options list.

Creates a schema with given params. Can also accept a keyword options list.

Deletes a schema

Similar to delete/1 but can also accept a keyword options list.

Deletes a schema. Can also accept a keyword options list.

Finds a schema with matching params. Can also accept a keyword options list.

Finds a schema by params and updates it or creates with results of params/update_params merged. Can also accept a keyword options list.

Finds a schema by params and updates it or creates with results of params/update_params merged. Can also accept a keyword options list.

Finds a schema by params or creates one if it isn't found. Can also accept a keyword options list.

Accepts a list of schemas and attempts to find them in the DB. Any missing Schemas will be created. Can also accept a keyword options list.

Gets a schema from the database

Gets a collection of schemas from the database but allows for a filter

Updates a schema with given updates. Can also accept a keyword options list.

Types

@type aggregate_options() :: :avg | :count | :max | :min | :sum
@type filter_params() :: Keyword.t() | map()
@type opts() :: Keyword.t()
@type query() :: Ecto.Query.t() | Ecto.Schema.t() | module()
@type schema_list() :: [Ecto.Schema.t()]
@type schema_res() :: {:ok, Ecto.Schema.t()} | {:error, any()}

Functions

Link to this function

aggregate(schema, params, aggregate, field, opts \\ [])

View Source
@spec aggregate(
  queryable :: query(),
  params :: filter_params(),
  agg_opts :: aggregate_options(),
  field :: atom(),
  opts()
) :: term()
@spec all(queryable :: query()) :: list()

Gets a collection of schemas from the database

Examples

iex> EctoSchemas.Actions.all(EctoSchemas.Accounts.User)
[]
@spec all(queryable :: query(), filter_params() | opts()) :: list()

Gets a collection of schemas from the database but allows for a filter or an options list.

Options

  • :repo - A module that uses the Ecto.Repo Module.

Examples

iex> Enum.each(1..4, fn _ -> create_user() end)
iex> length(EctoSchemas.Actions.all(EctoSchemas.Accounts.User, first: 3)) === 3
true

iex> Enum.each(1..4, fn _ -> create_user() end)
iex> length(EctoSchemas.Actions.all(EctoSchemas.Accounts.User, repo: MyApp.MyRepoModule.Repo)) === 3
true
Link to this function

all(query, params, opts)

View Source
@spec all(queryable :: query(), params :: filter_params(), opts()) :: list()

Similar to all/2 but can also accept a keyword options list.

Options

  • :repo - A module that uses the Ecto.Repo Module.

Examples

iex> Enum.each(1..4, fn _ -> create_user() end) iex> length(EctoSchemas.Actions.all(EctoSchemas.Accounts.User, first: 3, repo: MyApp.MyRepoModule.Repo)) === 3 true

Link to this function

create(schema, params, opts \\ [])

View Source
@spec create(schema :: module(), params :: filter_params(), opts()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}

Creates a schema with given params. Can also accept a keyword options list.

Options

  • :repo - A module that uses the Ecto.Repo Module.

Examples

iex> {:ok, schema} = EctoSchemas.Actions.create(EctoSchemas.Accounts.User, user_params(first_name: "TEST"))
iex> schema.first_name
"TEST"
iex> {:error, changeset} = EctoSchemas.Actions.create(EctoSchemas.Accounts.User, Map.delete(user_params(), :first_name))
iex> "can't be blank" in errors_on(changeset).first_name
true

Examples

iex> {:ok, schema} = EctoSchemas.Actions.create(EctoSchemas.Accounts.User, user_params(first_name: "TEST"), repo: MyApp.MyRepoModule.Repo)
iex> schema.first_name
true
@spec delete(schema_data :: Ecto.Schema.t() | schema_list() | module()) ::
  {:ok, Ecto.Schema.t()} | {:error, any()}

Deletes a schema

Examples

iex> user = create_user()
iex> {:ok, schema} = EctoSchemas.Actions.delete(user)
iex> schema.first_name === user.first_name
true
Link to this function

delete(schema_data, opts)

View Source
@spec delete(schema_data :: Ecto.Schema.t() | schema_list() | module(), opts()) ::
  {:ok, Ecto.Schema.t()} | {:error, any()}
@spec delete(schema :: module(), id :: integer()) ::
  {:ok, Ecto.Schema.t()} | {:error, any()}

Similar to delete/1 but can also accept a keyword options list.

Options

  • :repo - A module that uses the Ecto.Repo Module.

Examples

iex> user = create_user()
iex> {:ok, schema} = EctoSchemas.Actions.delete(user, repo: MyApp.MyRepoModule.Repo)
iex> schema.first_name === user.first_name
true
Link to this function

delete(schema, id, opts)

View Source
@spec delete(schema :: module(), id :: integer(), opts()) ::
  {:ok, Ecto.Schema.t()} | {:error, any()}

Deletes a schema. Can also accept a keyword options list.

Options

  • :repo - A module that uses the Ecto.Repo Module.

Examples

iex> user = create_user()
iex> {:ok, schema} = EctoSchemas.Actions.delete(EctoSchemas.Accounts.User, user.id)
iex> schema.first_name === user.first_name
true

iex> user = create_user()
iex> {:ok, schema} = EctoSchemas.Actions.delete(EctoSchemas.Accounts.User, user.id)
iex> schema.first_name === user.first_name
true
Link to this function

find(query, params, opts \\ [])

View Source
@spec find(queryable :: query(), params :: filter_params(), opts()) ::
  schema_res() | {:error, any()}

Finds a schema with matching params. Can also accept a keyword options list.

Options

  • :repo - A module that uses the Ecto.Repo Module.

Examples

iex> user = create_user()
iex> {:ok, schema} = EctoSchemas.Actions.find(EctoSchemas.Accounts.User, first_name: user.first_name)
iex> schema.first_name === user.first_name
true

iex> user = create_user()
iex> {:ok, schema} = EctoSchemas.Actions.find(EctoSchemas.Accounts.User, first_name: user.first_name, repo: MyApp.MyRepoModule.Repo)
iex> schema.first_name === user.first_name
true
Link to this function

find_and_update(schema, params, update_params, opts \\ [])

View Source
@spec find_and_update(query(), map(), map(), opts()) ::
  {:ok, Ecto.Schema.t()} | {:error, any()}

Finds a schema by params and updates it or creates with results of params/update_params merged. Can also accept a keyword options list.

Note: Relational filtering doesn't work on this function

Options

  • :repo - A module that uses the Ecto.Repo Module.
  • :replica - If you don't want to perform any reads against your Primary, you can specify a replica to read from.

Examples

iex> {:ok, schema} = EctoSchemas.Actions.find_and_update(EctoSchemas.Accounts.User, %{email: "some_email"}, %{name: "great name"})

iex> {:ok, schema} = EctoSchemas.Actions.find_and_update(EctoSchemas.Accounts.User, %{email: "some_email"}, %{name: "great name}, repo: MyApp.MyRepoModule.Repo, replica: MyApp.MyRepoModule.Repo.replica())
Link to this function

find_and_upsert(schema, params, update_params, opts \\ [])

View Source
@spec find_and_upsert(query(), map(), map(), opts()) ::
  {:ok, Ecto.Schema.t()} | {:error, any()}

Finds a schema by params and updates it or creates with results of params/update_params merged. Can also accept a keyword options list.

Note: Relational filtering doesn't work on this function

Options

  • :repo - A module that uses the Ecto.Repo Module.
  • :replica - If you don't want to perform any reads against your Primary, you can specify a replica to read from.

Examples

iex> {:ok, schema} = EctoSchemas.Actions.find_and_upsert(EctoSchemas.Accounts.User, %{email: "some_email"}, %{name: "great name"})

iex> {:ok, schema} = EctoSchemas.Actions.find_and_upsert(EctoSchemas.Accounts.User, %{email: "some_email"}, %{name: "great name}, repo: MyApp.MyRepoModule.Repo, replica: MyApp.MyRepoModule.Repo.replica())
Link to this function

find_or_create(schema, params, opts \\ [])

View Source
@spec find_or_create(query(), map(), opts()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}

Finds a schema by params or creates one if it isn't found. Can also accept a keyword options list.

Note: Relational filtering doesn't work on this function

Options

  • :repo - A module that uses the Ecto.Repo Module.
  • :replica - If you don't want to perform any reads against your Primary, you can specify a replica to read from.

Examples

iex> {:ok, schema} = EctoSchemas.Actions.find_or_create(EctoSchemas.Accounts.User, %{name: "great name"})

iex> {:ok, schema} = EctoSchemas.Actions.find_or_create(EctoSchemas.Accounts.User, %{name: "great name"}, repo: MyApp.MyRepoModule.Repo, replica: MyApp.MyRepoModule.Repo.replica())
Link to this function

find_or_create_many(schema, param_list, opts)

View Source
@spec find_or_create_many(
  query(),
  [map()],
  opts()
) :: {:ok, [Ecto.Schema.t()]} | {:error, [Ecto.Changeset.t()]}

Accepts a list of schemas and attempts to find them in the DB. Any missing Schemas will be created. Can also accept a keyword options list.

Note: Relational filtering doesn't work on this function

Options

  • :repo - A module that uses the Ecto.Repo Module.
  • :replica - If you don't want to perform any reads against your Primary, you can specify a replica to read from.

Examples

iex> {:ok, records} = EctoSchemas.Actions.find_or_create_many(EctoSchemas.Accounts.User, [%{name: "foo"}, %{name: "bar}]) iex> length(records) === 2

Link to this function

get(schema, id, opts \\ [])

View Source
@spec get(queryable :: query(), id :: term(), options :: Keyword.t()) ::
  Ecto.Schema.t() | nil

Gets a schema from the database

Examples

iex> user = create_user()
iex> %{id: id} = EctoSchemas.Actions.get(EctoSchemas.Accounts.User, user.id)
iex> id === user.id
true
iex> EctoSchemas.Actions.get(EctoSchemas.Accounts.User, 2504390) # ID nonexistant
nil
Link to this function

stream(query, params, opts \\ [])

View Source
@spec stream(queryable :: query(), params :: filter_params(), opts()) :: Enum.t()

Gets a collection of schemas from the database but allows for a filter

Link to this function

update(schema, schema_data, updates, opts \\ [])

View Source
@spec update(
  schema :: Ecto.Schema.t() | module(),
  id :: pos_integer() | String.t(),
  updates :: map() | Keyword.t(),
  opts()
) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}
@spec update(
  schema :: Ecto.Schema.t() | module(),
  schema_data :: Ecto.Schema.t(),
  updates :: map() | Keyword.t(),
  opts()
) :: {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}

Updates a schema with given updates. Can also accept a keyword options list.

Options

  • :repo - A module that uses the Ecto.Repo Module.
  • :replica - If you don't want to perform any reads against your Primary, you can specify a replica to read from.

Examples

iex> user = create_user()
iex> {:ok, schema} = EctoSchemas.Actions.update(EctoSchemas.Accounts.User, user, first_name: user.first_name)
iex> schema.first_name === user.first_name
true

iex> user = create_user()
iex> {:ok, schema} = EctoSchemas.Actions.update(EctoSchemas.Accounts.User, 1, first_name: user.first_name, repo: MyApp.MyRepoModule.Repo, replica: MyApp.MyRepoModule.Repo.replica())
iex> schema.first_name === user.first_name
true