udd*_*duu 4 elixir phoenix-framework
我刚开始吃凤凰,我不太明白一件事,我搜索并看到模式是数据库结构和模型具有较高的级别并处理逻辑,但在凤凰中我们只有模式,所以例如如果我会做一个密码哈希,它应该在用户模式中?或者我应该把它放在控制器中?
一般来说,您希望 MVC 应用程序具有“瘦控制器”——这是适用于多种语言的建议。在某些语言/框架中,这一点至关重要,因为测试控制器可能非常困难。尽管在像 Elixir 这样的函数式语言和像 Phoenix 这样结构良好的框架中测试控制器相对简单,但您仍然应该保持控制器尽可能精简。简而言之,控制器应该将服务模块(在 Phoenix 中通常称为“上下文”)与视图连接起来。通常它们根本没有太多逻辑。
“模式”可能是一个令人困惑的术语——花点时间理解不同的数据库使用不同的术语来指代(或多或少)相同的组件。例如,MySQL 中的“数据库”在 Oracle 或 Postgres 中称为“模式”。在 Ecto 中,“模式”类似于许多其他框架中的 ORM“模型”:Ecto 模式在代码中表示特定数据库表的“形状”(所以也许这就是他们使用相同术语的原因)。
但是,在您的情况下,密码哈希的计算字段之类的内容应该与 Ecto 模式位于同一模块中。(是的,Ecto 在代码中定义表格的形状时做了一些宏魔法,但它仍然是一个模块,并且是推荐放置的位置changeset
数据进入数据库之前放置处理验证和变异数据的函数)。
如果您发现自己想知道某些功能应该放在哪里,请问问自己,如果用户输入来自 CLI 而不是来自 Web,则应将代码放在哪里。如果您有一个使用密码创建用户的 CLI 混合任务,您会使用 Web 控制器吗?不,您不会:控制器只是连接 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
Run Code Online (Sandbox Code Playgroud)
下面是一个使用 package.json 计算要存储在数据库中的密码哈希值的示例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
Run Code Online (Sandbox Code Playgroud)
希望有帮助。
归档时间: |
|
查看次数: |
702 次 |
最近记录: |