我有一个带有名称和密码属性的用户模型。当用户点击“编辑”时,我希望只有名称字段可以编辑和验证,而不是密码字段。反之亦然,当用户点击“重置密码”时。 我认为我的主要问题是如何在名称字段编辑期间关闭密码验证,如何在密码编辑期间关闭名称验证?
edit.html.erb
<%= form_for @user, html: { class: "form_settings" } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<p><span><%= f.label :name %></span>
<%= f.text_field :name %>
</p>
<p style="padding-top: 15px"><span> </span>
<%= f.submit "Submit", class: "submit" %>
</p>
<% end %>
reset_password.html.erb
<%= form_for @user, html: { class: "form_settings" } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<p><span><%= label_tag :old_password, "Current Password" %></span>
<%= password_field_tag :old_password %>
</p>
<p><span><%= f.label :password %></span>
<%= f.password_field :password %>
</p>
<p><span><%= f.label :password_confirmation %></span>
<%= f.password_field :password_confirmation %>
</p>
<p style="padding-top: 15px"><span> </span>
<%= f.submit "Submit", class: "submit" %>
</p>
<% end %>
users_controller.rb
def update
@user = User.find(params[:id])
if params[:old_password]
if @user.authenticate(params[:old_password])
@user.update_attributes(password: params[:user][:password])
flash[:success] = "Password has been updated"
redirect_to @user
else
flash.now[:error] = "Current password is incorrect"
render :reset_password
end
elsif @user.update_attributes(params[:user])
flash[:success] = "User name updated"
redirect_to @user
else
render :edit
end
end
我的另一个问题是密码和password_confirmation验证无效。这就是我在模型中所拥有的:
validates :password, presence: true, confirmation: true
更新 获得了重置密码,验证使用此代码:
def update
@user = User.find(params[:id])
if params[:old_password]
if @user.authenticate(params[:old_password])
if params[:user][:password] == params[:user][:password_confirmation]
@user.update_attributes(password: params[:user][:password])
flash[:success] = "Password has been updated"
redirect_to @user
else
flash.now[:error] = "Passwords don't match"
render :reset_password
end
else
flash.now[:error] = "Current password is incorrect"
render :reset_password
end
elsif @user.update_attributes(params[:user])
flash[:success] = "User name updated"
redirect_to @user
else
render :edit
end
end
但对我来说这似乎太复杂了。有人看到更简单的解决方案吗?
但我仍然有编辑名称字段的问题。这是说密码不能为空。
答案 0 :(得分:1)
将验证逻辑移至模型并保持控制器清洁。
validates :password, presence: true, confirmation: true, if: password?, on: :update
validates :name, presence: true, if: name?, on: :update
创建记录时,这是必需的。只需添加on: :create
validates :password, presence: true, confirmation: true, on: :create
validates :name, presence: true, on: :create
并像这样修改你的控制器,
def update
@user = User.find(params[:id])
@user.authenticate(params[:old_password]) if params[:old_password]
return redirect_to @user, notice: "Sucessfully updated" if @user.update_attributes(params[:user])
render Rails.application.routes.recognize_path(request.referer)[:action]
end
此链接中使用的渲染理念: Render the action that initiated update
答案 1 :(得分:1)
您不应在同一操作中混合名称编辑和密码重置。
创建一个将更新用户属性的操作,password
字段不应与attr_accessible
创建另一个处理密码重置的操作。
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
flash[:success] = "User name updated"
redirect_to @user
else
render :edit
end
end
def reset_password
if params[:old_password] && @user.authenticate(params[:old_password])
if params[:user][:password] == params[:user][:password_confirmation]
@user.password = params[:user][:password]
flash[:success] = "Password has been updated"
redirect_to @user
else
flash.now[:error] = "Passwords don't match"
render :reset_password
end
else
flash.now[:error] = "Current password is incorrect"
render :reset_password
end
end
这样,每个动作都有其语义角色。
顺便说一句,我希望您使用像bcrypt这样的东西来存储密码。
答案 2 :(得分:0)
想出来......但它看起来有点难看:
def update
@user = User.find(params[:id])
if params[:old_password]
if @user.authenticate(params[:old_password])
if params[:user][:password] == params[:user][:password_confirmation]
@user.update_attributes(password: params[:user][:password])
flash[:success] = "Password has been updated"
redirect_to @user
else
flash.now[:error] = "Passwords don't match"
render :reset_password
end
else
flash.now[:error] = "Current password is incorrect"
render :reset_password
end
elsif params[:user][:name].blank?
flash[:error] = "Name can't be blank"
render :edit
else
@user.update_attribute(:name, params[:user][:name])
flash[:success] = "User name updated"
redirect_to @user
end
end