Ruby on rails Rails 3.1+;设计1.4.9:为什么';ActiveRecord是否捕获失败的保存?
更新:我正在使用Desive 1.4.9进行身份验证,我的Desive生成的用户模型似乎没有捕获数据库在尝试创建一个新用户时抛出的异常,该用户的电子邮件地址已存在于数据库中。在遵循cicloon的建议(参见下面的回复)之后,我创建新用户的代码是Ruby on rails Rails 3.1+;设计1.4.9:为什么';ActiveRecord是否捕获失败的保存?,ruby-on-rails,ruby-on-rails-3,activerecord,ruby-on-rails-3.1,Ruby On Rails,Ruby On Rails 3,Activerecord,Ruby On Rails 3.1,更新:我正在使用Desive 1.4.9进行身份验证,我的Desive生成的用户模型似乎没有捕获数据库在尝试创建一个新用户时抛出的异常,该用户的电子邮件地址已存在于数据库中。在遵循cicloon的建议(参见下面的回复)之后,我创建新用户的代码是 class Api::RegistrationsController < Api::BaseController respond_to :json def create user = User.new(params[:user]
class Api::RegistrationsController < Api::BaseController
respond_to :json
def create
user = User.new(params[:user])
user.ensure_authentication_token!
if user.valid?
user.save
render :json=> user.as_json(:auth_token=>user.authentication_token, :email=>user.email, :user_id=>user.id), :status=>201
return
else
warden.custom_failure!
render :json=> user.errors, :status=>422
end
end
end
这是用户模型
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :token_authenticatable
attr_accessible :email, :password, :password_confirmation, :remember_me, :authentication_token
validates_uniqueness_of :email
def ensure_authentication_token!
reset_authentication_token! if authentication_token.blank?
end
def as_json(options={})
super(:only => [:email, :authentication_token, :id])
end
end
如何让我的代码返回带有错误描述的422
非常感谢你的智慧 我认为您可能需要将验证添加到您的用户模型中
validates_uniqueness_of :email
我又读了你的帖子,现在我知道那里发生了什么。您有一个数据库索引,Rails不知道,因此当您创建@user.save时,数据库会抛出一个Rails未捕获的异常 也就是说,您有两个选择: 1.)在Rails中捕获异常:
begin
user.save
render :json=> user.as_json(:auth_token=>user.authentication_token, :email=>user.email, :user_id=>user.id), :status=>201
rescue
warden.custom_failure!
render :json=> user.errors, :status=>422
end
2.)将验证添加到您的模型并检查用户。有效吗?:
在您的用户模型上:
validates_uniqueness_of :email
在控制器上:
if user.valid?
user.save
render :json=> user.as_json(:auth_token=>user.authentication_token, :email=>user.email, :user_id=>user.id), :status=>201
return
else
warden.custom_failure!
render :json=> user.errors, :status=>422
end
我会将其包装在异常处理程序中。试着这样做:
class Api::RegistrationsController < Api::BaseController
respond_to :json
def create
user = User.new(params[:user])
status = nil
json = nil
begin
user.ensure_authentication_token!
user.save!
status = 201
json = {
:auth_token => user.authentication_token,
:email => user.email,
:user_id => user.id
}
rescue StandardError => e
case e
when ActiveRecord::StatementInvalid, ActiveRecord::RecordNotUnique
# ActiveRecord::StatementInvalid -> Raised by SQLite Adapter
# ActiveRecord::RecordNotUnique -> Raised by Postgres Adapter
user.errors[:email] = 'already taken'
end
warden.custom_failure!
status = 422
json = user.errors
end
render :json => json, :status => status
end
end
class Api::RegistrationControlleruser.authentication_token,
:email=>user.email,
:user_id=>user.id
}
营救标准错误=>e
案例e
当ActiveRecord::StatementInvalid时,ActiveRecord::RecordNotUnique
#ActiveRecord::StatementInvalid->由SQLite适配器引发
#ActiveRecord::RecordNotUnique->由Postgres适配器引发
user.errors[:email]=“已拍摄”
结束
典狱长,你失败了!
状态=422
json=user.errors
结束
呈现:json=>json,:status=>status
结束
结束
您能提供一些日志吗?我想你的索引可能还没有创建,所以保存并不是真的失败。有什么特别的日志吗?除了我上面发布的SQLite3错误之外,服务器日志实际上没有显示太多内容。有什么方法可以让我查看为我的模型创建的标识吗?谢谢,cicloon,我尝试了两种建议,但都没有成功。请查看我的更新问题以查看我的当前代码。再次感谢你的帮助!没关系,我发现了问题。我必须移动调用以确保if user.valid下的\u身份验证\u令牌?行,该修复的ituser.save不会引发异常。user.save!将引发验证异常和数据库异常。看到postgres和sqlite驱动程序以不同的方式报告异常,我有点难过。还要注意的是,我还没有测试过这个w/MySQL,它可能也会做一些完全不同的事情。我还要注意的是,这并不是一个真正针对设计的问题。归根结底,db索引是唯一可以可靠地强制唯一性的东西。Sebi提到的验证器在大多数情况下都能很好地工作,但不是所有情况。最终,您必须处理db异常以捕获所有场景。
if user.valid?
user.save
render :json=> user.as_json(:auth_token=>user.authentication_token, :email=>user.email, :user_id=>user.id), :status=>201
return
else
warden.custom_failure!
render :json=> user.errors, :status=>422
end
class Api::RegistrationsController < Api::BaseController
respond_to :json
def create
user = User.new(params[:user])
status = nil
json = nil
begin
user.ensure_authentication_token!
user.save!
status = 201
json = {
:auth_token => user.authentication_token,
:email => user.email,
:user_id => user.id
}
rescue StandardError => e
case e
when ActiveRecord::StatementInvalid, ActiveRecord::RecordNotUnique
# ActiveRecord::StatementInvalid -> Raised by SQLite Adapter
# ActiveRecord::RecordNotUnique -> Raised by Postgres Adapter
user.errors[:email] = 'already taken'
end
warden.custom_failure!
status = 422
json = user.errors
end
render :json => json, :status => status
end
end