我是Rails的新手,有几个关于验证参数和返回错误响应的问题。我想使用新的Rails 5 API模式创建一个JSON API。
据我所知,Rails建议使用“强参数”作为验证参数的基线。例如,如果我想创建一个需要电话号码或电子邮件的User类,我会在UsersController中以类似的方式开始。
def create
@user = User.new(create_user_params)
end
def create_user_params
params.require(:user).permit(:email, :phone)
end
现在,如果我想要更复杂的东西,我可以添加以下内容
def create
arr_contains_at_least_one(params[:user], [:email, :phone])
@user = User.new(create_user_params)
end
这引出了我的问题。
在出现默认Rails错误(ActionController :: ParameterMissing)或自定义错误的情况下,返回“漂亮”错误响应的最佳方法是什么?我的意思是,如果我在浏览器中调用API端点,它将返回带有描述性消息的可读JSON。如果我在生产模式下运行我的服务器,并且在第一个示例中未能提供用户参数,则rails返回:
An unhandled lowlevel error occurred. The application logs may have details.
这显然不好,特别是如果我希望向最终用户显示错误。在这里,我假设强参数模式是为了安全性和数据完整性,而不是用户体验。模型字段验证似乎也是如此。所以我做了以下调整。
def create
return error_response("some error") unless arr_contains_at_least_one(params[:user], [:email, :phone])
@user = User.new(create_user_params)
end
def error_response(msg, status = 400)
render json: {"code":status, "message": msg}, :status => status
end
这有效,但现在我不得不手动编写参数检查(检查是否存在强制参数,以及验证电子邮件地址等参数)及其相应的错误响应。如果我也在模型上使用Rails的内置字段验证,这似乎违反了DRY原则。此外,设计良好的错误处理模式需要相当多的自定义实现。
我错过了一些Rails魔术还是我在正确的轨道上?
编辑:看起来主动记录验证可以很容易地包装在JSON响应中(http://guides.rubyonrails.org/active_record_validations.html),但仍然存在验证参数是否存在的问题。
答案 0 :(得分:3)
我认为您对strong_parameters
与验证方法的使用感到困惑。
强参数提供了一个界面,用于保护属性不受最终用户分配的影响。这使得动作控制器参数被禁止在活动模型批量分配中使用,直到它们被列入白名单。
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
如果将参数列入强参数白名单,则表示您可以将它们大量分配给ActiveRecord模型。或者更好的是,未列入白名单的属性不会传递给您的模型。
它们实际上与验证本身无关。它们旨在保护您的模型以进行不允许的参数注入。
def create
@user = User.new(create_user_params)
end
def create_user_params
params.require(:user).permit(:email, :phone)
end
所以你的例子:
POST /users body={user: {email: 'some@email.com', phone: '1234', some_other: 'some other'}}
some_other
属性不会传递到您的User.new
您正在寻找的是IS activerecord验证。在你的具体情况下,我会写一些类似的东西:
def create
@user = User.new(create_user_params)
if @user.save
render json: @user
else
render @user.errors.full_messages.as_json, status: 400
end
end
def create_user_params
params.require(:user).permit(:email, :phone)
end
然后在你的模型中:
class User < ActiveRecord::Base
validates_precense_of :some_other #this will cause the user not to save, end thus, report an errer message
end
答案 1 :(得分:1)
&#34; Rails方式&#34;应该使用表单往返 - 所有验证应该存在于模型中。控制器可能只有简单的验证,如安全性和白名单,与业务逻辑无关。 &#34;型号&#34;可能不仅是ActiveRecord本身,而且还有类似FormObject https://robots.thoughtbot.com/activemodel-form-objects的东西,特别是如果你的一些资源没有一对一地反映到数据库表中。
如果您打算只使用API模式,我建议您给一个非常整洁的API DSL机会 https://github.com/ruby-grape/grape#parameter-validation-and-coercion