Ex Operation Save

A library for making domain operations in Elixir

Project README

ExOperation

Build Status

A library for making domain operations wrapped in a single database transaction.

Resources

Example

An operation definition:

defmodule MyApp.Book.Update do
  use ExOperation, params: %{
    id!: :integer,
    title!: :string,
    author_id: :integer
  }

  def validate_params(changeset) do
    changeset
    |> Ecto.Changeset.validate_length(:title, min: 5)
  end

  def call(operation) do
    operation
    |> find(:book, schema: MyApp.Book, preload: [:author])
    |> find(:author, schema: MyApp.Author, id_path: [:author_id], optional: true)
    |> step(:result, &do_update(operation.context, &1, operation.params))
    |> after_commit(&send_notifcation(&1))
  end

  defp do_update(context, txn, params) do
    txn.book
    |> Ecto.Changeset.cast(params, [:title])
    |> Ecto.Changeset.put_assoc(:author, txn.author)
    |> Ecto.Changeset.put_assoc(:updated_by, context.current_user)
    |> MyApp.Repo.update()
  end

  defp send_notification(txn) do
    # …
    {:ok, txn}
  end
end

The call:

context = %{current_user: current_user}

with {:ok, %{result: book}} <- MyApp.Book.Update |> ExOperation.run(context, params) do
  # …
end

Usage with Phoenix

An example Phoenix app can be found here: ex_operation_phoenix_example.

Features

  • Railway oriented domain logic pipeline.
  • Running all steps in a single database transaction. It uses Ecto.Multi inside.
  • Params casting & validation with Ecto.Changeset. Thanks to params library.
  • Convenient fetching of entitites from the database.
  • Context passing. Useful for passing current user, current locale etc.
  • Composable operations: one operation can call another through suboperation/3 function.
  • Changing operation scenario based on previous steps results with defer/2.
  • Hooks: before_transaction/1, after_commit/1.

Installation

Add the following to your mix.exs and then run mix deps.get:

def deps do
  [
    {:ex_operation, "~> 0.5.0"}
  ]
end

Add to your config/config.exs:

config :ex_operation,
  repo: MyApp.Repo

where MyApp.Repo is the name of your Ecto.Repo module.

Open Source Agenda is not affiliated with "Ex Operation" Project. README Source: feymartynov/ex_operation
Stars
35
Open Issues
1
Last Commit
4 years ago

Open Source Agenda Badge

Open Source Agenda Rating