Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 创建失败时RubyonRails活动记录返回值?_Ruby On Rails_Ruby_Activerecord_Rails Activerecord - Fatal编程技术网

Ruby on rails 创建失败时RubyonRails活动记录返回值?

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

我是RubyonRails新手,在获得这项工作时遇到了困难。基本上,我有一个用户注册页面,其中有一个密码确认。在User类中,我进行了以下验证:

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
会引发一些异常。