🔥
paramsの中身がIntegerになる場合がある
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]の部分に入れておいてくれるんですよね。
でもそうなると、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みたいに書くようです。
paramsのところは、JSON文字列を渡すみたいです。試しにHashを渡すとエラーになりました。
to_jsonをつけるとうまくいきます。
今回のコード
Discussion