如何用ExMachina创建可登录的Phoenix用户账号?
解决Factory创建可登录用户的问题
核心问题
你当前的Factory直接给hashed_password赋值明文字符串,登录时系统用Bcrypt.verify_pass/2验证密码,明文无法匹配哈希值导致失败;同时手动构造结构体跳过了User模块的changeset逻辑,没利用自动哈希密码的机制。另外你设置的密码"password"长度仅8位,不符合User里validate_password要求的最小12位规则。
解决方案
修改Factory,通过User模块的registration_changeset构建用户,让changeset自动处理密码哈希和验证:
defmodule HealthTracker.Factory do use ExMachina.Ecto, repo: HealthTracker.Repo def user_factory do %HealthTracker.Accounts.User{} # 调用注册changeset,传入符合规则的邮箱和密码 |> HealthTracker.Accounts.User.registration_changeset(%{ email: sequence(:email, &"email-#{&1}@example.com"), password: "password123456" # 长度≥12,满足验证要求 }) # 应用changeset得到处理后的用户结构体 |> Ecto.Changeset.apply_changes() # 手动设置已验证状态,确保可直接登录 |> Map.put(:confirmed_at, NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)) end end
为什么这样有效
- 自动哈希密码:
registration_changeset会触发maybe_hash_password逻辑,将明文密码用Bcrypt哈希后赋值给hashed_password,同时删除虚拟字段password。 - 符合验证规则:changeset自动校验密码长度、邮箱格式等,避免手动构造结构体时出现无效数据。
- 模拟已验证状态:手动设置
confirmed_at,确保用户处于可登录的已验证状态(如果你的登录逻辑要求邮箱验证)。
验证效果
重新在iex中插入用户:
$ iex -S mix phx.server iex> Factory.insert(:user)
此时数据库中hashed_password会是Bcrypt生成的合法哈希字符串,使用对应密码即可正常登录。
内容的提问来源于stack exchange,提问作者martins
相关产品推荐
相关产品推荐

