在使用以下版本时,我遇到了问题帖子中报告的相同问题
红宝石 2.3.2
导轨(5.0.0.1)
rspec-rails (3.5.2)
在网上搜索问题时,我在https://github.com/rails/rails/issues/26069发现了一个相关问题,它建议的解决方案是在控制器测试中使用它们时将as: :json
选项传递给post
, etc 方法(有关更多详细信息,请参阅评论https://github.com/rails/rails/issues/26069#issuecomment-240916233get
中引用的 PR )。使用该解决方案并没有解决我遇到的参数混合问题。以下是我在推荐解决方案中使用的不同类型数据的结果:
在我的控制器规格中,我有以下内容
before(:each) do
request.accept = "application/json"
end
在测试日志中,我确实看到正在处理请求
Processing by Api::V1::MyController#my_action as JSON
数据-1
data = [
{
param_1: "param_1_value",
},
{
param_2: "param_2_value",
}
]
params.merge!(my_data: data)
post :my_action, params: params, as: :json
最终在请求参数中如下
{ "my_data"=> [ {"param_1"=>"param_1_value", "param_2"=>"param_2_value"} ] }
这是错误的。
数据-2
data = [
{
param_1: "param_1_value",
something_else: ""
},
{
param_2: "param_2_value",
another_thing: ""
}
]
params.merge!(my_data: data)
post :my_action, params: params, as: :json
最终在请求参数中如下
{ "my_data"=> [ {"param_1"=>"param_1_value", "something_else"=>"", "another_thing"=>"", "param_2"=>"param_2_value"} ] }
这是错误的。
数据-3
data = [
{
param_1: "param_1_value",
param_2: ""
},
{
param_1: ""
param_2: "param_2_value",
}
]
params.merge!(my_data: data)
post :my_action, params: params, as: :json
最终在请求参数中如下
{ "my_data"=>[ {"param_1"=>"param_1_value", "param_2"=>""}, {"param_1"=>"", "param_2"=>"param_2_value"} ] }
这是正确的。
应该注意的是,对于没有该选项的Data-3as: :json
,我在请求参数中也收到了正确的数据。
还有一件事:在评论中https://github.com/rails/rails/issues/26069#issuecomment-240358290建议处理上述问题的替代解决方案如下
另一个解决方法是将嵌套属性指定为不是数组而是哈希:
params = {
id: @book.id,
book: {
title: 'Cool',
pages_params: {
"0" => { id: @page.id, content: 'another content' },
"1" => { id: @delete_page.id, _destroy: 1 },
"2" => { content: 'another new page' }
}
},
format: :json
}
不幸的是,这已从嵌套属性的文档中删除,所以我不知道这是否会保持有效。
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
但是这个解决方案有一个缺点是我们需要手动清理控制器端的数据以将其恢复到预期的结构,即哈希数组。
最后,我在下面分享对我有用的东西
规范/shared_contexts.rb
RSpec.shared_context "common helpers" do
def set_request_header(request_obj:, request_header_name:, request_header_value:)
request_obj.headers[request_header_name] = request_header_value
end
def set_request_header_content_type_as_json(request_obj:)
set_request_header(request_obj: request_obj, request_header_name: 'CONTENT_TYPE', request_header_value: 'application/json')
end
end
然后在我的规范文件中
require 'shared_contexts'
RSpec.describe Api::V1::MyController, :type => :controller do
include_context "common helpers"
context "POST #my_action" do
it "my example" do
data = [
{
param_1: "param_1_value",
},
{
param_2: "param_2_value",
}
]
params.merge!(my_data: data)
set_request_header_content_type_as_json(request_obj: request)
post :my_action, params: params
end
end
end
可以看出,设置请求标头CONTENT_TYPE
是使请求参数以预期结构接收的缺失。