You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写RSwag Spec实现GET请求传参至Rails控制器?

问题

如何编写RSwag Spec,让GET请求能将my_field: 'my_value'传入控制器的params中?

初始尝试

路由配置(config/routes.rb)

Rails.application.routes.draw do
  namespace :api do
    resources :my_tests
  end
end

控制器代码(app/controllers/api/my_tests_controller.rb)

class Api::MyTestsController < Api::BaseController
  def index
    render json: do_something_with(params) # 期望`params[:my_field] == 'my_value'`
  end
end

初始RSwag测试代码(spec/api/my_tests/index_spec.rb)

RSpec.describe 'Test', type: :request do
  context 'on openapi spec' do
    let(:Authorization) { bearer_token }

    path '/api/my_tests' do
      get 'Test' do
        consumes 'application/json'
        produces 'application/json'
        security [bearerAuth: {}]
        parameter name: :my_field, in: :body, type: :string

        response '200', 'Test' do
          let(:my_field) { 'my_value' }

          run_test!
        end
      end
    end
  end
end

运行后得到的params不符合预期:

{
  "\"my_value\"": nil,
  controller: "api/my_tests",
  action: "index",
  my_test: {}
}
尝试复用POST请求的解决方案

之前找到的适用于POST请求的参数配置方案,放到GET请求里完全不起作用。修改后的测试代码如下:

RSpec.describe 'Test', type: :request do
  context 'on openapi spec' do
    let(:Authorization) { bearer_token }

    path '/api/my_tests' do
      get 'Test' do
        consumes 'application/json'
        produces 'application/json'
        security [bearerAuth: {}]
        parameter name: :body, in: :body, schema: {
          type: :object,
          properties: {
            my_field: { type: :string },
          },
        }

        response '200', 'Test' do
          let(:body) { { my_field: 'my_value' } }

          run_test!
        end
      end
    end
  end
end

结果生成的params还是不对:

{
  "{\"my_field\":\"my_value\"}": nil,
  controller: "api/my_tests",
  action: "index",
  my_test: {}
}

但如果把请求改成POST,就能得到完全符合预期的params:

{
  "my_field": "my_value", # <- 这是期望获取的字段
  "controller": "api/my_tests",
  "action": "foo",
  "my_test": {
    "my_field": "my_value"
  }
}
正确解决方案

方案1:遵循HTTP规范,使用URL查询参数(推荐)

GET请求的参数本来就应该放在URL的查询字符串里,而非请求体中,这是HTTP的规范约定,RSwag对GET请求的body参数处理逻辑也和POST完全不同。只需要把测试里的参数位置改成:query即可:

RSpec.describe 'Test', type: :request do
  context 'on openapi spec' do
    let(:Authorization) { bearer_token }

    path '/api/my_tests' do
      get 'Test' do
        produces 'application/json'
        security [bearerAuth: {}]
        # 将参数放到query中
        parameter name: :my_field, in: :query, type: :string

        response '200', 'Test' do
          let(:my_field) { 'my_value' }

          run_test!
        end
      end
    end
  end
end

这样控制器里的params[:my_field]就能正确获取到'my_value',最终生成的params会是:

{
  "my_field": "my_value",
  controller: "api/my_tests",
  action: "index"
}

方案2:强制给GET请求加请求体(不推荐)

如果业务上确实需要GET请求带请求体(强烈不建议,因为很多HTTP客户端和服务器对这种情况的处理不一致,容易出现兼容性问题),可以手动在测试里设置请求体,并指定内容类型:

RSpec.describe 'Test', type: :request do
  context 'on openapi spec' do
    let(:Authorization) { bearer_token }

    path '/api/my_tests' do
      get 'Test' do
        consumes 'application/json'
        produces 'application/json'
        security [bearerAuth: {}]

        response '200', 'Test' do
          before do
            # 手动设置请求body和内容类型
            request.body = { my_field: 'my_value' }.to_json
            request.content_type = 'application/json'
          end

          run_test!
        end
      end
    end
  end
end

内容的提问来源于stack exchange,提问作者Augustinas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 20:05:04