我需要在控制器方法中检查一堆条件。 1)这是一团糟2)它甚至没有击中正确的重定向。
def password_set_submit
password_check = /^(?=.*[a-z]{1,})(?=.*[A-Z]{1,})(?=.*\d{1,}){8,}.+$/
@user = User.find(session[:id])
if params[:password] && params[:password_confirmation] && params[:username] && params[:old_password]
if params[:password] == params[:password_confirmation] && params[:password] =~ password_check
# do some api stuff here
if @user.save
flash[:success] = 'Password updated.'
redirect_to login_path and return
end
end
if params[:password] != params[:password_confirmation]
flash[:error] = 'Passwords did not match.'
redirect_to password_set_path and return
end
if params[:password] == params[:password_confirmation] && params[:password] !~ password_check
flash[:error] = 'Passwords did not match password criteria.'
redirect_to password_set_path and return
end
end
else
flash[:error] = 'Please fill all inputs.'
redirect_to password_set_path and return
end
end
这需要执行以下操作:
1)如果提交的参数少于4个,则重定向并显示“填写所有输入”
2)如果密码和密码确认彼此不匹配,请重定向并显示“密码不匹配”
3)如果密码和密码确认相互匹配但与条件不符,则重定向并显示“密码与条件不匹配”
4)如果密码和密码确认相互匹配且符合条件,请进行api呼叫并重定向登录
我没有if / else想法,我希望清理它会帮助我正确地修改重定向。
答案 0 :(得分:2)
Rails的方法是使用模型验证。
class User < ActiveRecord::Base
validates :password, confirmation: true, presence: true# password must match password_confirmation
validates :password_confirmation, presence: true # a password confirmation must be set
end
如果我们尝试创建或更新没有匹配pw / pw确认的用户,操作将失败。
irb(main):006:0> @user = User.create(password: 'foo')
(1.5ms) begin transaction
(0.2ms) rollback transaction
=> #<User id: nil, password: "foo", password_confirmation: nil, created_at: nil, updated_at: nil>
irb(main):007:0> @user.errors.full_messages
=> ["Password confirmation can't be blank"]
irb(main):008:0>
在处理用户密码时,你应该永远不会以纯文本形式将它们存储在数据库中!
由于大多数用户重复使用通用密码,您可能还会损害他们的电子邮件,银行帐户等。您可能会在财务上和法律上承担责任,这可能会破坏您的职业生涯。
答案是使用加密密码。由于这非常容易出错,Rails有一些名为has_secure_password
的东西可以加密和验证密码。
您要做的第一件事就是从password
数据库中删除password_confirmation
和users
列。
添加password_digest
列。然后将has_secure_password
添加到您的模型中。
class User < ActiveRecord::Base
PASSWORD_CHECK = /^(?=.*[a-z]{1,})(?=.*[A-Z]{1,})(?=.*\d{1,}){8,}.+$/
has_secure_password
validates :password, format: PASSWORD_CHECK
end
这会自动为password
和password_confirmation
的密码,确认以及获取者和设置者添加验证。
要检查旧密码是否正确,我们会这样做:
@user = User.find(session[:id]).authenticate(params[:old_password])
# user or nil
这是Rails方式的一个例子:
class UsersController
# We setup a callback that redirects to the login if the user is not logged in
before_action :authenticate_user!, only: [ :password_set_submit ]
def password_set_submit
# We don't want assign the the old_password to user.
unless @user.authenticate(params[:old_password])
# And we don't want to validate on the model level here
# so we add an error manually:
@user.errors.add(:old_password, 'The current password is not correct.')
end
if @user.update(update_password_params)
redirect_to login_path, notice: 'Password updated.'
else
# The user failed to update, so we want to render the form again.
render :password_set, alert: 'Password could not be updated.'
end
end
private
# Normally you would put this in your ApplicationController
def authenticate_user!
@user = User.find(session[:id])
unless @user
flash.alert('You must be signed in to perform this action.')
redirect_to login_path
end
end
# http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
def update_password_params
params.require(:user).permit(:password, :password_confirmation)
end
end
请注意我们行动中的逻辑如何简单得多?用户已更新,我们重定向或无效,我们重新呈现表单。
我们不会在每个错误中创建一条Flash消息,而是在表单上显示错误:
<%= form_for(@user, url: { action: :password_set_submit}, method: :patch) do |f| %>
<% if @user.errors.any? %>
<div id="error_explanation">
<h2>Your password could not be updated:</h2>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<%= f.label :password, 'New password' %>
<%= f.password_field_tag :password %>
</div>
<div class="row">
<%= f.label :password_confirmation %>
<%= f.password_field_tag :password_confirmation %>
</div>
<div class="row">
<p>Please provide your current password for confirmation</p>
<%= f.label :old_password, 'Current password' %>
<%= f.password_field_tag :old_password %>
</div>
<%= f.submit 'Update password' %>
<% end %>
答案 1 :(得分:0)
我会从控制器中删除与此密码重置相关的所有代码,并将其放入自己的模型//Changables
var playerMoves = 0
var solidNumbers =[ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "and So on"]
//Functions
func checkForPlayerMovesEqual12() {
//What a very long function name XD
if playerMoves / 12 == solidNumbers {
//Do this } else {
//Do this if else }
中:
User::PasswordReset
这样可以将控制器的方法更改为更简单的方法:
# in app/models/user/password_reset.rb
class User::PasswordReset
attr_reader :user, :error
PASSWORD_REGEXP = /^(?=.*[a-z]{1,})(?=.*[A-Z]{1,})(?=.*\d{1,}){8,}.+$/
def initialize(user_id)
@user = User.find(user_id)
end
def update(parameters)
if parameters_valid?(parameters)
# do some api stuff here with `user` and `parameters[:password]`
else
false
end
end
private
def valid?
error.blank?
end
def parameters_valid?(parameters)
parameter_list_valid(parameters.keys) &&
password_valid(params[:password], params[:password_confirmation])
end
def parameter_list_valid(keys)
mandatory_keys = [:password, :password_confirmation, :username, :old_password]
unless mandatory_keys.all? { |key| keys.include?(key) }
@error = 'Please fill all inputs.'
end
valid?
end
def password_valid(password, confirmation)
if password != confirmation
@error = 'Passwords did not match.'
elsif password !~ PASSWORD_REGEXP
@error = 'Passwords did not match password criteria.'
end
valid?
end
end
完成此重构后,您可以更轻松地在条件中查找问题并扩展代码。