我正在尝试为用户无法输入电子邮件地址的上下文自定义 Devise 注册控制器,因为他们的电子邮件之前已手动输入,然后才能访问注册页面。为了在 UI 中实现此目的,我重写了
new.html.erb
模板来预填充电子邮件字段并将其在 HTML 中标记为禁用:
<%= f.email_field :email, autocomplete: "email", disabled: true %>
我在覆盖的注册控制器中预填写了电子邮件:
def new
super do |resource|
resource.email = required_email
end
end
不幸的是,在 Rails 中,这意味着提交表单时生成的 POST 调用没有电子邮件参数†。这实际上很好,因为我不希望用户能够通过解决禁用字段或以不同的方式注入不同的地址来修改浏览器中的电子邮件。问题是我还需要将此电子邮件插入到
create
操作中的结果参数中,以便正确验证用户对象。
我尝试覆盖控制器中的参数:
def signup_params
super.merge(email: required_email)
end
我也尝试过设置资源属性,就像我在
new
操作中所做的那样(如上所示)。
这些都没有任何结果,因为我仍然收到“电子邮件不能为空”的验证错误。我试图深入研究 Devise 源代码来检查表单参数的处理方式,但它是一个足够复杂的系统,我看不到任何简单的钩子或方法来调用来修改流程。
† 我知道这是
disabled
字段的预期行为,我实际上将该字段实现为 readonly
,但是我在这里使用 disabled
,因为理论上我也希望能够添加参数即使表格中没有相应字段。
答案是完全回避设计并在 Rails 级别注入参数:
def create
params[:user].merge!(email: required_email)
# Other override code
end