我正在使用RubyonRails7构建一个REST API,该API通过HTTP PATCH接受有效负载,如下所示:
{
"answers": [
{"question_id": 1, "content": "My answer content ONE"},
{"question_id": 2, "content": "My answer content TWO"}
]
}
我想在我的控制器中使用强参数来验证这个响应的结构。
我试过很多类似的SO帖子,但似乎都不适合我。
以下是我迄今为止所尝试的:
params = ActionController::Parameters.new(answers: [{question_id: 1, content: 'some answer'}])
params.require(answers: [:question_id, :content])
# I get: `require': param is missing or the value is empty: {:answers=>[:question_id, :content]} (ActionController::ParameterMissing)
params.require(:answers).require([:question_id, :content])
# I get: NoMethodError on the second .require
params.require(answers: [[:question_id, :content]])
# I get: param is missing or the value is empty: {:answers=>[[:question_id, :content]]}
如果能指出我做错了什么,我们将不胜感激。
我刚发布问题就找到了解决方案。
有效的解决方案是:
def answer_params
params.require(:answer).each do |answer_param|
answer_param.require(%i[question_id, answer])
end
end
这使我能够确保以正确的结构提供所有值,并在我的控制器方法中使用它,如下所示:
def update
answer_params.each do |answer_param|
puts answer_param['question_id']
puts answer_param['answer']
end
end
为什么坚持只通过ActionController::Parameters
验证参数?我总是发现params API对嵌套结构(我为API构建了更深入的结构(的限制,就像你一样,在这种情况下,我总是以最基本的方式验证数据。例如,对于您显示的数据结构,我将以以下方式进行验证:
def validate_answers_data
received_answers_arr = params[:answers]
if received_answers_arr.blank?
# return error requires answers not received
return
end
whitelisted_answers_data = []
received_answers_arr.each do |h|
question_id = h[:question_id]
answer_content = h[:content]
if question_id.present? && answer_content.present?
whitelisted_answers_data << { question_id: question_id, content: answer_content }
end
end
if whitelisted_answers_data.blank?
# return error answers data received found invalid
return
end
whitelisted_answers_data
end
Params API对白名单数据肯定很有用,但当它对特定的数据结构造成限制时,与其坚持只通过API实现验证,不如通过纯Ruby构造实现,这是一个始终开放的选项。
希望你觉得这个建议有用。
您可以定义方法来确保params结构如下:
def answer_params
params.permit(answers: %i[question_id content])
end
然后在update
操作中使用此方法,如:
def update
answer_params[:answers].each do |answer_param|
puts answer_param['question_id']
puts answer_param['answer']
end
end