hidden_field_tag 如何在重置密码表单中工作
How does hidden_field_tag works in an reset password form
很难理解表单在特定情况下如何与 hidden_field_tag 一起工作。我希望有人能向我解释发生了什么。
这是来自railstutorial重置密码的表格。
我的观点是:
<% provide(:title, 'Reset password') %>
<h1>Reset password</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user, url: password_reset_path(params[:id])) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= hidden_field_tag :email, @user.email %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Update password", class: "btn btn-primary" %>
<% end %>
</div>
</div>
我的更新操作和强参数方法:
def update
if params[:user][:password].empty?
@user.errors.add(:password, "can't be empty")
render 'edit'
elsif @user.update_attributes(user_params)
log_in @user
@user.update_attribute(:reset_digest, nil)
flash[:success] = "Password has been reset."
redirect_to @user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
访问编辑操作时,用户输入一封电子邮件,应用会向该电子邮件发送一个 link,并带有激活令牌,如下所示:
/password_resets/9Ij91DFChTeWTitNDVJfYw/edit?email=example%40railstutorial.org
用户打开此 link 并更改密码。这是完美的功能。我的问题是:如果我已经从编辑操作中获得用户并且没有在我的更新操作中明确使用 params[:email]
(随 hidden_field_tag 提供),为什么我需要隐藏标签?
动作是相互独立的。当您首次在 edit
操作范围内呈现密码重置表单时,您的 @user
实例变量(之前以某种方式初始化)用于为隐藏的电子邮件字段提供值。
当稍后用户提交表单时,其数据会在完全独立的请求中由 update
操作处理。这个请求不知道之前发生了什么,具体来说,表单最初是由 edit
动作渲染的。它也无权访问 edit
操作范围内的任何对象。
为了处理请求,您的 update
操作代码需要重新初始化它需要的所有对象,主要是 @user
对象。
如果当前操作不知道之前发生了什么,它怎么知道应该将哪个用户记录转到 @user
变量?它可以通过电子邮件找到用户,这就是您在参数中提供它的原因。您的 edit
操作代码使其可用于下一个请求。
从您的 edit
动作来看,您的控制器中应该已经有一些方法可以在执行动作代码之前初始化 @user
对象。寻找 before_action
回调。
该方法可能通过 params
中传递的电子邮件查找用户。当动作本身被执行时,@user
对象已经存在,因此它似乎 Rails 不知何故知道如何获取它。它不会,您的控制器代码使它发生。
因此您需要隐藏标签来在操作之间传递上下文。还有其他方法可以做到这一点,比如使用 session
或 cookies
,但这种方法可能是最简单的。
很难理解表单在特定情况下如何与 hidden_field_tag 一起工作。我希望有人能向我解释发生了什么。
这是来自railstutorial重置密码的表格。
我的观点是:
<% provide(:title, 'Reset password') %>
<h1>Reset password</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user, url: password_reset_path(params[:id])) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= hidden_field_tag :email, @user.email %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Update password", class: "btn btn-primary" %>
<% end %>
</div>
</div>
我的更新操作和强参数方法:
def update
if params[:user][:password].empty?
@user.errors.add(:password, "can't be empty")
render 'edit'
elsif @user.update_attributes(user_params)
log_in @user
@user.update_attribute(:reset_digest, nil)
flash[:success] = "Password has been reset."
redirect_to @user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
访问编辑操作时,用户输入一封电子邮件,应用会向该电子邮件发送一个 link,并带有激活令牌,如下所示:
/password_resets/9Ij91DFChTeWTitNDVJfYw/edit?email=example%40railstutorial.org
用户打开此 link 并更改密码。这是完美的功能。我的问题是:如果我已经从编辑操作中获得用户并且没有在我的更新操作中明确使用 params[:email]
(随 hidden_field_tag 提供),为什么我需要隐藏标签?
动作是相互独立的。当您首次在 edit
操作范围内呈现密码重置表单时,您的 @user
实例变量(之前以某种方式初始化)用于为隐藏的电子邮件字段提供值。
当稍后用户提交表单时,其数据会在完全独立的请求中由 update
操作处理。这个请求不知道之前发生了什么,具体来说,表单最初是由 edit
动作渲染的。它也无权访问 edit
操作范围内的任何对象。
为了处理请求,您的 update
操作代码需要重新初始化它需要的所有对象,主要是 @user
对象。
如果当前操作不知道之前发生了什么,它怎么知道应该将哪个用户记录转到 @user
变量?它可以通过电子邮件找到用户,这就是您在参数中提供它的原因。您的 edit
操作代码使其可用于下一个请求。
从您的 edit
动作来看,您的控制器中应该已经有一些方法可以在执行动作代码之前初始化 @user
对象。寻找 before_action
回调。
该方法可能通过 params
中传递的电子邮件查找用户。当动作本身被执行时,@user
对象已经存在,因此它似乎 Rails 不知何故知道如何获取它。它不会,您的控制器代码使它发生。
因此您需要隐藏标签来在操作之间传递上下文。还有其他方法可以做到这一点,比如使用 session
或 cookies
,但这种方法可能是最简单的。