Phoenix Framework是否使用任何类型的回调过滤器,例如Rails中的回调过滤器?我知道可以验证更改集,但我正在寻找实施before_create
,before_save
和after_commit
等操作的方法。
答案 0 :(得分:13)
Ecto:https://hexdocs.pm/ecto/#!Ecto.Model.Callbacks.html
它们与Rails的不同之处在于:它们接收并且必须返回变更集,并且必须用于数据一致性(不要使用它们来发送电子邮件而不是它们)。
答案 1 :(得分: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
另一种方法是使用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
使用
运行它result = Repo.transaction(Service.password_reset(account, params))
您必须记住,您必须执行与数据相关的查询,而不是执行其他任务,例如发送电子邮件。为此,您可以简单地对结果进行模式匹配并执行适当的操作。如果事务成功,请让您想发送邮件,如果不是
则显示一些错误消息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
来源: