gpt4 book ai didi

elixir - 模式和模型有什么区别?

转载 作者:行者123 更新时间:2023-12-03 23:47:45 25 4
gpt4 key购买 nike

我刚开始吃 Phoenix ,我不太了解一件事,我搜索并看到模式是数据库结构和模型具有高级别的逻辑处理,但在 Phoenix 我们只有模式,例如,如果我会做一个密码哈希,它应该在用户模式中?或者我应该把它放在 Controller 中?

最佳答案

一般来说,您希望您的 MVC 应用程序具有“瘦 Controller ”——这是适用于多种语言的建议。在某些语言/框架中,这很关键,因为测试 Controller 可能非常困难。尽管使用 Elixir 等函数式语言和 Phoenix 等结构良好的框架测试 Controller 相对简单,但您仍应尽可能保持 Controller 精简。简而言之, Controller 应该将服务模块(在 Phoenix 中通常称为“上下文”)与 View 连接起来。通常它们根本没有很多逻辑。

“模式”可能是一个令人困惑的术语——花点时间了解不同的数据库使用不同的术语来指代(或多或少)相同的组件。例如。 MySQL 中的“数据库”在 Oracle 或 Postgres 中称为“模式”。在 Ecto 中,“模式”类似于许多其他框架中的 ORM“模型”:Ecto 模式在代码中表示特定数据库表的“形状”(所以也许这就是它们使用相同术语的原因)。

但是,在您的情况下,密码哈希的计算字段之类的内容应该与 Ecto 模式位于同一模块中。 (是的,当 Ecto 在代码中定义表格的形状时,它做了一些宏魔术,但它仍然是一个模块,并且推荐放置 changeset 函数,这些函数在数据进入数据库之前处理验证和变异数据) .

如果您发现自己想知道某些功能应该放在哪里,请问问自己,如果用户输入来自 CLI 而不是来自 Web,您会将代码放在哪里。如果你有一个 CLI 混合任务创建一个带密码的用户,你会使用 Web Controller 吗?不,您不会: Controller 只是将 Web 请求/响应与底层模型/模式连接起来的中间人。您不希望仅仅因为您想为 CLI 脚本创建计算密码哈希的代码而复制它,这样您就有了放置它的逻辑位置:在模式中。

Ecto 变更集允许您在进入数据库的过程中修改数据。在某些框架中,您可能会听到这被称为“突变”或“计算字段”。

这是一个计算“created_at”字段的示例(是的,您可以在数据库中执行此操作,但它是如何在代码中执行计算字段的有用示例):

  @doc false
def changeset(user, attrs) do
user
|> cast(attrs, [:username,:email])
|> validate_required([:username,:email])
|> add_created_at()
|> unique_constraint(:username)
|> unique_constraint(:email)
end

defp add_created_at(changeset) do
case changeset do
%Ecto.Changeset{
valid?: true,
changes: _user
} ->
put_change(
changeset,
:created_at,
DateTime.utc_now
|> DateTime.truncate(:second)
)
_ ->
changeset
end
end

下面是一个计算要存储在数据库中的密码哈希的示例——使用 Argon2包裹。这还添加了一个字段,用于标识用于散列密码的算法(作为字符串,可供引用):
  def changeset(user, attrs) do
user
|> cast(attrs, [:username, :password])
|> validate_required([:username, :password])
|> validate_length(:password, min: 8, max: 100)
|> unique_constraint(:username)
|> put_password_hash()
end


defp put_password_hash(changeset) do
case changeset do
%Ecto.Changeset{
valid?: true,
changes: %{
password: plain_text
}
} ->
put_change(changeset, :password_hash, Argon2.hash_pwd_salt(plain_text))
|> put_change(:algorithm, "argon2")

_ ->
changeset
end
end

希望有帮助。

关于elixir - 模式和模型有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61491863/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com