Ell*_*son 3 elixir ecto phoenix-framework
在create/insert上添加计算值的最佳实践方法是什么?我应该为创建和更新创建唯一的变更集吗?
比方说,我有一个博客文章模型,我想创建一个标题slug值并存储它.这有点做作,但出于某种原因说我只想在创建而不是更新时设置它.我应该做以下事情吗?
defmodule MyBlog.Post do
use MyBlog.Web, :model
schema "posts" do
field :title, :string
field :title_slug, :string
field :content, :text
timestamps
end
@required_fields ~w(
title
content
)
@optional_fields ~w()
def create_changeset(model, params \\ :empty) do
changeset(model, params)
|> generate_title_slug
end
defp changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
defp generate_title_slug(changeset) do
put_change(changeset, :title_slug, __some_slug_generation_code__)
end
def update_changeset(model, params \\ :empty) do
changeset(model, params)
end
end
Run Code Online (Sandbox Code Playgroud)
我强烈反对回调 - 它们难以测试,引入全局状态,模糊不清,难以推理.这也违背了Elixir的核心原则之一:"明确胜过隐性".
Ecto的核心团队甚至正在考虑摆脱回调,或改变名称并减少暴露.在没有其他可能的情况下,使用回调应该是最后的选择.
为了展示回调的问题之一,让我们想象一下你确实使用回调来解决这个问题的场景.现在,您正在设计一个管理界面,您不希望出现此行为.你是如何解决这个问题的?你开始走下禁用回调的兔子洞,在异常时引入异常,并且有一个难以理解的多分支条件逻辑.但这一起解决了一个错误的问题!
对于Ecto的架构,不同的变更集方法非常精细且非常自然.通过这种方式,您可以对不同的操作进行不同的验证,而且不会是全局的 让我们考虑如何在我之前展示的场景中解决问题.它非常简单 - 您创建另一个变更集功能!
我见过几次的解决方案是将changeset函数更改为在第一个类型中采用三个参数和模式匹配,例如:
def changeset(action, model, params \\ :empty)
def changeset(:create, model, params)
# return create changeset
end
def changeset(:update, model, params)
# return update changeset
end
Run Code Online (Sandbox Code Playgroud)
我不确定哪个更好 - 一个函数中的多个函数或模式匹配.这主要是偏好问题.
| 归档时间: |
|
| 查看次数: |
1292 次 |
| 最近记录: |