Ruby on rails 创建失败时RubyonRails活动记录返回值?
我是RubyonRails新手,在获得这项工作时遇到了困难。基本上,我有一个用户注册页面,其中有一个密码确认。在User类中,我进行了以下验证:Ruby on rails 创建失败时RubyonRails活动记录返回值?,ruby-on-rails,ruby,activerecord,rails-activerecord,Ruby On Rails,Ruby,Activerecord,Rails Activerecord,我是RubyonRails新手,在获得这项工作时遇到了困难。基本上,我有一个用户注册页面,其中有一个密码确认。在User类中,我进行了以下验证: validates :password, confirmation: true 在控制器里我有 def create vals = params[:user] if(User.exists(vals[:username])) flash[:warning] = "#{vals[:username]} already
validates :password, confirmation: true
在控制器里我有
def create
vals = params[:user]
if(User.exists(vals[:username]))
flash[:warning] = "#{vals[:username]} already exists! Please try a new one. "
else
vals[:create_date] = DateTime.current
user = User.create(vals, :without_protection => :true)
if user==false or user==nil or user==vals
flash[:warning] = "#{vals[:username]} has not been registered successfully. "
else
flash[:notice] = "#{vals[:username]} has been registered. "
end
end
redirect_to users_path
end
问题是,当密码与确认匹配时,我仍然会收到通知消息,显示注册成功。如您所见,我尝试了几个create
的返回值,但没有一个成功。我非常确定验证工作正常,因为如果密码与确认不匹配,我就看不到刚才创建的用户。另外,当我使用create代码>,我可以看到网站因验证错误而崩溃。有人能告诉我当记录未被验证时,create
应该返回什么吗
谢谢 您的问题的答案是,User.create
在成功或失败时返回一个User
实例。如果由于验证而失败,则该实例将无效,并将出现错误:
user.valid? # <= returns false
user.errors.count # <= will be > 0
user.errors.blank? # <= will be false
为此:
if !user.valid?
您也可以使用此模式:
user.attributes = vals
if user.save
... save succeeded ...
else
... save failed ...
end
save
方法返回一个布尔值true
或false
,因为您在现有实例上调用它
但让我们通过其他一些方式让您走上正确的轨道:
首先:您有:
if User.exists(vals[:username])
vals[:create_date] = DateTime.current
user = User.create(vals, :without_protection => :true)
(我假设exits
是您在User
模型上使用的一种方法,因为这不是Rails的事情)。您可以在模型上使用另一个验证,而不是在控制器中执行该检查:
class User < ActiveRecord::Base
...
validates :username, unique: true
...
end
这是不必要的。如果在
向模型中添加一个名为created_的列,它将自动保存创建日期(由ActiveRecord管理)。在迁移过程中,您可以将其及其合作伙伴updated_at
添加到您的模型中,如下所示:
create_table :users do |t|
...
t.timestamps # <= tells rails to add created_at and updated_at
end
现在,您将始终拥有用户模型的创建日期/时间和上次更新,而不需要额外的代码
第三:您有:
if User.exists(vals[:username])
vals[:create_date] = DateTime.current
user = User.create(vals, :without_protection => :true)
不要这样做。相反,请更改以下内容:
vals = params[:user]
为此:
vals = params.require(:user).permit(:username, :password, :password_confirmation)
然后继续保护:
user = User.create(vals)
您可以在permit()
调用中添加要从表单中引入的任何其他列。这是非常重要的,因为以后很难解决这类问题。“如果你一旦走上黑暗之路,它将永远主宰你的命运。”
Fourth:如果保存失败,您不应该重定向到user\u路径
,因为将没有要显示的用户模型。相反,您应该重新呈现新的表单。对于错误,您也不需要flash消息。如果新的表单呈现,它可以检查@user.errors
并相应地报告错误消息。看
最后:您提到,即使正确确认了密码,您的验证也会失败。如果没有看到您的表单代码,我无法确定,但请确保您的密码字段名为password
,确认字段名为password\u confirmation
。Rails在验证确认时专门查找此*\u确认
字段值
如果还不行,请发布表单代码,我会修改。答案是ActiveRecord对象。官方源代码显示create
在对象成功或失败时返回该对象:
# File activerecord/lib/active_record/persistence.rb, line 29
def create(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create(attr, &block) }
else
object = new(attributes, &block)
object.save
object
end
end
如何判断成功或失败
真正的答案是持久化?
:
if user.persisted?
# Success
else
# Failed
end
为什么不使用user.valid?
来执行此操作?因为有时,当一些回调操作其他模型失败时,这是不够的:
class One < ActiveRecord::Base
has_many :twos
after_create :create_twos_after_create
def create_twos_after_create
# Use bang method in callbacks, than it will rollback while create two failed
twos.create!({}) # This will fail because lack of the column `number`
end
end
class Two < ActiveRecord::Base
validates :number, presence: true
end
class-One
现在,我们执行One.create
将失败,检查日志文件,这将是一个回滚,因为它无法创建两个。在这种情况下,One.create.valid?
仍然返回true
,但它实际创建失败,因此有必要使用One.create.persistend?
替换它
注意:该代码在Rails 5.1中进行了测试。不带保护的参数做什么?它在这里允许质量分配。我不认为这会干扰验证。您的意思是,当密码与确认不匹配时,您仍然会收到成功消息吗?因为另一种方法应该是正确的功能。还有一件事需要补充:如果可能,尝试在出现错误时引发异常,这是停止进程并返回错误消息的好方法。\valid?
方法将查询数据库的有效性user.errors.blank?
如果您忘记在自定义验证中记录错误(未验证),则可能返回true。如果某些数据库权限出现问题(一般情况下),会发生什么情况?我觉得#create
会引发一些异常。