Phoenix Framework Callbacks

Does the Phoenix Framework use any types of callback filters, such as those found in Rails ? I know that you can check the set of changes, but I am looking for ways to implement actions such as before_create , before_save and after_commit .

+8
elixir phoenix-framework
source share
2 answers

Ecto does: https://hexdocs.pm/ecto/#!Ecto.Model.Callbacks.html

They are noticeably different from Rails: they receive and should return a set of changes and should be used for data consistency (do not use them to send e-mail, and what not).

+13
source share

Callbacks are completely removed from Ecto 2.0.

So, how to handle callbacks now ?. Here are two ways:

For before_ you can use Changeset . One of the reasons callbacks that were deleted was that many developers relied on callbacks in many cases where there would be enough change sets. So just apply the required function to your change set,

 def changeset(post, params \\ :empty) do post |> cast(params, @required_params, @optional_params) |> validate_length(:title, min: 3) |> validate_length(:metadata, min: 3) |> implement_a_before_callback end def implement_a_before_callback(changeset) #Apply required actions and return Changeset end 

Another way is to combine multiple repo operations using Ecto.Multi . From the documents

Ecto.Multi allows you to package operations that must be performed together (in the same transaction with the database), and allows you to analyze operations in a queue without actually executing them. Each operation is assigned a unique name and will identify its result or help determine the place of failure in case of its occurrence. Therefore, when you want a group of operations related to data to occur immediately, you can use Multi , here the before_ and after_ callbacks can be replaced.

An example would be

  # In defmodule Service def password_reset(account, params) do Multi.new |> Multi.update(:account, Account.password_reset_changeset(account, params)) |> Multi.insert(:log, Log.password_reset_changeset(account, params)) |> Multi.delete_all(:sessions, assoc(account, :sessions)) end 

Run it using

 result = Repo.transaction(Service.password_reset(account, params)) 

You must remember that you must complete data-related queries and not perform other tasks, such as sending emails. To do this, you can simply combine the template with the result and perform the corresponding action. Let's sit that you want to send mail if the transaction was successful, and display some error message if not

 case result do {:ok, %{account: account, log: log, sessions: sessions}} -> # Operation was successful, perform actions like sending a mail {:error, failed_operation, failed_value, changes_so_far} -> # One of the operations failed. Raise error message end 

A source:

+11
source share

All Articles