创建了一个线程here,但它没有解决我的问题。
我的代码是:
- 课程. rb**
class Course < ApplicationRecord
COURSE_TYPES = %i( trial limited unlimited )
enum course_type: COURSE_TYPES
validates_inclusion_of :course_type, in: COURSE_TYPES
end
- 课程_控制器. rb**
class CoursesController < ApiController
def create
course = Course.new(course_params) # <-- Exception here
if course.save # <-- But I expect the process can go here
render json: course, status: :ok
else
render json: {error: 'Failed to create course'}, status: :unprocessable_entity
end
end
private
def course_params
params.require(:course).permit(:course_type)
end
end
我的测试用例:
- 课程控制器规范rb**
describe '#create' do
context 'when invalid course type' do
let(:params) { { course_type: 'english' } }
before { post :create, params: { course: params } }
it 'returns 422' do
expect(response.status).to eq(422)
end
end
end
在运行上述测试用例时,我得到了ArgumentError
异常,在Rails issues中对此进行了描述
因此,如果我将一个无效的course_type
设置为枚举,它将在验证阶段失败,而不是引发异常。
另外,我知道在here的rails中的钩子下真正发生了什么,我不想在分配枚举类型值的每个代码块中手动拯救这种异常!
对此有何建议?
5条答案
按热度按时间vlju58qv1#
我找到了一个解决方案,我自己在Rails6中测试过。
用法:
lnvxswe22#
已更新以支持
.valid?
具有幂等验证。这个解决方案并不十分优雅,但它确实有效。
我们在一个API应用程序中遇到了这个问题。我们不喜欢每次需要在任何控制器或动作中使用时都
rescue
这个错误的想法。所以我们在模型端rescue
处理它,如下所示:可以说,rails团队选择引发
ArgumentError
而不是validation error是正确的,因为我们可以完全控制用户可以从单选按钮组中选择什么选项,或者可以选择select
字段,所以如果程序员碰巧添加了一个新的单选按钮,其值有拼写错误,那么最好引发一个error,因为这是一个应用程序错误。而不是用户错误。然而,对于API,这将不起作用,因为我们不再能够控制发送到服务器的值。
kfgdxczn3#
想介绍另一种解决方案。
这将避免控制器中的
ArgumentError
。在我的Rails 6应用程序中运行良好。b1payxdu4#
使用Dmitry的逻辑的上述答案,我对ActiveRecord模型进行了此动态解决方案
解决方案1:
更新。
解决方案2:这里有另一种动态复制到其他模型的方法。
x一个一个一个一个x一个一个二个x
wvt8vs2t5#
上面的answer by Aliaksandr不适用于Rails 7.0.4,因为
decorate_attribute_type
方法是removed in Rails 7,并且与attribute
方法统一。因此,上述解决方案将引发类似于以下内容的
NoMethodError
:要在Rails7中实现该解决方案,请考虑使用以下修改后的关注点: