🔥

paramsの中身がIntegerになる場合がある

2024/07/17に公開

GETだろうと、POSTだろうと、HTTPリクエストで飛んでくるものは全てStringになっていると思ってましたが、そうでないパターンもありました。

でも、railsだとリクエストのbodyにjsonが含まれている場合はそうではなかったです。
例えば、curlだとこんな感じです。

curl -X POST -H "Content-Type: application/json" -d '{"page": 1}' http://127.0.0.1:3000/api/sample

rails側はこんな感じです。

module Api
  # sample
  class SampleController < ApplicationController
    def index
      page = params[:page]
      render json: { page:, type: page.class }
    end
  end
end

curlでリクエストした様子が↓です。

pageパラメータがIntegerになっているのがわかると思います。
bodyがjsonだろうと勝手に変換してparams[:page]の部分に入れておいてくれるんですよね。
https://railsguides.jp/v7.1/api_app.html#actiondispatch-requestを使う

でもそうなると、String#match?みたいなメソッドは失敗します。

# 抜粋
def index
  page = params[:page]

  page.match?(/\A\d\z/)

  render json: { page:, type: page.class }
end

こんな感じで実行
curl -X POST -H "Content-Type: application/json" -d '{"page": 1}' http://127.0.0.1:3000/api/sample

こんなエラー

Started POST "/api/sample" for 127.0.0.1 at 2024-07-16 09:35:33 +0900
  ActiveRecord::SchemaMigration Load (0.1ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by Api::SampleController#index as */*
  Parameters: {"page"=>1, "sample"=>{"page"=>1}}
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms | Allocations: 508)


  
NoMethodError (undefined method `match?' for an instance of Integer):
  
app/controllers/api/sample_controller.rb:9:in `index'

なので、今回はto_sするという感じで落ち着きました。

rspecはどう書く?

↓のProviding JSON dataみたいに書くようです。
https://rspec.info/features/6-1/rspec-rails/request-specs/request-spec/
paramsのところは、JSON文字列を渡すみたいです。

試しにHashを渡すとエラーになりました。

to_jsonをつけるとうまくいきます。

今回のコード

https://github.com/na8esin/rails_react/tree/d9d0704828d23d2252c822b77708f180a4a98c72/rails71

しくみのテックブログ

Discussion