ruby-on-rails - 验证错误:“密码不能为空”,但不能为空
问题描述
它一直说密码字段和密码确认字段为空白,即使我使用 rails 控制台创建新用户也是如此。此外,密码确认的错误消息重复出现,我不知道为什么。任何帮助将不胜感激。
用户模型
class User < ApplicationRecord
has_secure_password
validates_confirmation_of :password
attr_accessor :password
validates :password, length: 6..100, confirmation: true
validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, on: :create }
before_save :encrypt_password
validates_presence_of :password_confirmation, if: lambda {| u| u.password.present? }
def encrypt_password
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password,password_salt)
end
end
用户控制器
class UsersController < ApplicationController
def new
@user = User.new
end
def index
end
def show
@user = User.find(params[:id])
end
def create
@user = User.new(user_params)
if @user.save and user.valid?
session[:user_id] = @user.id
render 'users/new'
else
render :action => "new"
end
end
private
def user_params
params.required(:user).permit(:name, :email, :password, :password_confirmation)
end
end
用户/注册视图
<%= stylesheet_link_tag "signup.css" %>
<div id = signup_image></div>
<div id = signup-background>
<div id = signup-text>
<h1 style = "color: rgb(40,50,60);">Sign up</h1>
<%= form_for :user,url: '/users' do |f| %>
<br> <%= f.text_field :name, placeholder: "Name", class: 'signup-textfield'%><br>
<br><%= f.text_field :email, placeholder:"email@gmail.com", class: 'signup-textfield' %><br>
<br><%= f.password_field :password, placeholder: "Password",class: 'signup-textfield' %><br>
<br><%= f.password_field :password_confirmation, placeholder: "Confirm password",class: 'signup-textfield' %><br>
<br>
<%= f.submit id: "signup-button"%>
<% end %>
<br>
<small>Already have an account? <%=link_to "Login here", "/login" %></small>
</div>
</div>
用户新视图
<div id = signup_image></div>
<div id = signup-background>
<div id = signup-text>
<h1 style = "color: rgb(40,50,60);">Sign up</h1>
<div class="row">
<div class="span6 offset3">
<%= render :partial => 'shared/error_message_form' %>
</div>
</div>
<%= form_for @user do |f| %>
<br> <%= f.text_field :name , placeholder: "Name", class: 'signup-textfield'%>
<br><%= f.text_field :email, placeholder:"email@gmail.com", class: 'signup-textfield' %>
<br><%= f.password_field :password_digest, placeholder: "Password",class: 'signup-textfield' %>
<br><%= f.password_field :password_confirmation, placeholder: "Confirm password",class: 'signup-textfield' %>
<br>
<%= f.submit id: "signup-button"%>
<% end %>
<br><br>
<small>Already have an account? <%=link_to "Login here", "/login" %></small>
</div>
</div>
错误消息的部分
<% if @user.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
<%= pluralize(@user.errors.count, "error")%> detected while signing up.
</div>
<ul>
<br>
<% @user.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
en.yml 文件
en:
hello: "Hello world"
activerecord:
models:
user:
attributes:
user:
email: "Email address"
errors:
models:
user:
attributes:
email:
blank: "cannot be empty"
taken: "%{value} is already taken"
解决方案
这里有很多问题,如果您是新手,这很正常。
模型
这实际上就是您所需要的:
class User < ApplicationRecord
has_secure_password
validates :email,
format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
end
has_secure_password
为您设置密码加密。您不需要手动加密密码。您也不需要设置任何验证,因为它已经为您设置了它们:- 创建时必须存在密码
- 密码长度应小于或等于 72 字节
- 密码确认(使用 XXX_confirmation 属性)
如果你想提供你自己的验证逻辑,你应该使用它
has_secure_password(validations: false)
来避免重复验证。但首先要学会使用框架。仅使用
attr_accessor :password
clobbers 创建的 setterhas_secure_password
。它几乎不应该在模型中使用。仅在创建时验证电子邮件格式是没有意义的。
控制器
class UsersController < ApplicationController
def new
@user = User.new
end
def index
end
def show
@user = User.find(params[:id])
end
def create
@user = User.new(user_params)
if @user.save
session[:user_id] = @user.id
redirect_to root_path, notice: 'Welcome! ...'
else
render :new
end
end
private
def user_params
# the method is called require not required
params.require(:user)
.permit(:name, :email, :password, :password_confirmation)
end
end
.save
.valid?
在尝试保存记录之前调用。因此@user.save and user.valid?
完全是多余的。您还应该始终检查返回值,.save
而不是.valid?
在极少数情况下验证可能会通过,但数据库可能仍会拒绝插入查询。- 使用
&&
而不是and
关键字,因为后者具有不同的运算符优先级。 - 您应该在注册后将用户重定向到有意义的地方,而不是
render 'users/new'
. render 'users/new'
和 renderrender :action => "new"
都是render :new
.
看法
不要重复表格。使用部分:
# app/views/users/_form.html.erb
<%= form_with(model: user) do |f| %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name, class: 'signup-textfield'%>
</div>
<div class="field">
<%= f.label :email %>
<%= f.email_field :email, placeholder: "email@example.com", class: 'signup-textfield' %>
</div>
<div class="field">
<%= f.label :password %>
<%= f.password_field :password, class: 'signup-textfield' %>
</div>
<div class="field">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'signup-textfield' %>
</div>
<div class="actions">
<%= f.submit id: "signup-button" %>
</div>
<% end %>
<div id = signup_image></div>
<div id = signup-background>
<div id = signup-text>
<h1 style = "color: rgb(40,50,60);">Sign up</h1>
<div class="row">
<div class="span6 offset3">
<%= render partial: 'shared/error_message_form' %>
</div>
</div>
<%= render partial: 'form', locals: { user: @user } %>
<small>Already have an account? <%=link_to "Login here", "/login" %></small>
</div>
</div>
- 您缺少密码输入!
- 不要使用密码摘要的输入!它从明文输入在服务器上生成,并且永远不应该真正暴露给用户。
- 停止使用
<br>
标签。使用内容标签(例如<div>
)来包装输入和标签,以便可以使用 CSS 设置样式,不再是 2005 年了。<br>
只能用于将文本分成几行。不适用于视觉间距。 - 不要使用
placeholder
属性代替标签。它是一种对可用性和可访问性来说非常糟糕的反模式。 - 使用约定而不是配置,只需将模型实例传递给
form_with
/form_for
。Rails 可以自己找出路径。避免使用符号 - 调用表单form_for :user
。执行的实例变量/方法查找不那么明确,并且被认为是 Rails 魔术的一个案例。这种行为没有延续到form_with
. - 你真的需要一个单独的用户/注册视图来复制整个事情吗?
推荐阅读
- oracle - 需要知道我是否在 PL/SQL 的存储过程中正确使用了 IF 语句
- python - 更新 Kivy 中子对象小部件的位置(Python 不是 .kv)
- c - 为什么此代码有“内联文件中的 EOF”错误,我该怎么做才能修复它?
- php - 为什么这个 MySQLi 准备语句无法更新数据库?
- regex - vs代码不能在PCRE2模式下使用正则表达式组引用替换
- python - Pandas 样式的默认浮点格式
- c# - 如何禁止某些单元格调整行或列的大小
- python - 在数据框上使用 groupby().sum(),然后绘制带有标签的饼图?
- html - Sass 风格不适用于内容
- npgsql - 有没有办法覆盖 Azure DB for PostgreSQL 上的服务器配置“statement_timeout”?