凤凰城框架回调

woh*_*ert 8 elixir phoenix-framework

Phoenix Framework是否使用任何类型的回调过滤器,例如Rails中的回调过滤器?我知道这是可能来验证的变更,但是我正在寻找方法来实现,例如动作before_create, before_saveafter_commit.

Jos*_*lim 13

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

它们与Rails的不同之处在于:它们接收并且必须返回变更集,并且必须用于数据一致性(不要使用它们来发送电子邮件,而不是用于发送电子邮件).


cod*_*hal 13

从Ecto 2.0开始,回调已被完全删除.

那么如何处理回调呢?这有两种方式

对于before_回调,您可以使用Changeset本身.删除回调的原因之一是因为许多开发人员在很多情况下依赖于回调就足够了.因此,只需将所需的功能应用于您的变更集,

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
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用Ecto.Multi将多个repo操作组合在一起.来自文档

Ecto.Multi可以打包应该一起执行的操作(在单个数据库事务中),并提供一种内省排队操作的方法,而无需实际执行它们.每个操作都有一个唯一的名称,它将识别其结果,或者有助于在发生故障时识别故障位置.所以每当你想要一组相关的操作一次,你可以用它来发生的数据Multi,都before_after_回调可以在这里取代.

一个例子是

  # 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 Code Online (Sandbox Code Playgroud)

运行它

result = Repo.transaction(Service.password_reset(account, params))
Run Code Online (Sandbox Code Playgroud)

您必须记住,您必须执行与数据相关的查询,而不是执行其他任务,例如发送电子邮件.为此,您可以简单地对结果进行模式匹配并执行适当的操作.如果事务成功,请让您想发送邮件,如果没有则显示一些错误消息

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
Run Code Online (Sandbox Code Playgroud)

资源: