Rails6 のちょい足しな新機能を試す74（parsed_body 編）

# はじめに

（多分）Rails 6 に追加された新機能を試す第74段。 今回は、 `parsed_body` 編です。
Rails 6 では、 Controller Test で `ActionDispatch::TestResponse#parsed_body` メソッドの結果が、適切な値になるように修正されました。

Ruby 2.6.3, Rails 6.0.0.rc2, RSpec(rspec-rails) 3.8.2, Rails 5.2.3 で確認しました。

Rails 6.0.0.rc2 は `gem install rails -v 6.0.0rc2 --prerelease` でインストールできます。

(Rails 6.0.0 がリリースされていますが、確認した当時は、 Rails 6.0.0.rc2 が最新でした。悪しからず :bow:)

```shell
$ rails --version
Rails 6.0.0.rc2
```

今回は、rspec で constroller spec で確認してみます。
rspec では、controller spec は非推奨で、 request spec が推奨されています。
ですが、 request spec では、現象を確認できなかったので、あえて、 controller spec で確認します。

RSpec は導入済みであるとして話を進めます。
RSpec の設定などは [Docker で RSpec の System Spec を実行するための設定メモ](https://qiita.com/suketa/items/d783ac61c2a3e4c16ad4) を参照してください。

# User の CRUD を作ります。

ちょっと手抜きで User の CRUD を作成します。

```shell
$ bin/rails g scaffold User name
```

# Controller を変更する

index で json を返すように変更します。

(別にこんなことしなくても `http://localhost:3000/users.json` で json が返されるのですが、 Rails 6 の controller spec で index.json を呼び出す方法がわからなかったので、あえて、こうしてます。)

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
  ...
  def index
    @users = User.all
    render json: @users.to_json # この行を追加
  end
  ...
end
```

# controller spec を書く

`parsed_body` メソッドの結果を確認するようにします。

`parsed_body` の結果が文字列ではなく配列であること、配列の1番目の要素(Hash) の `name` の値が `user.name` に等しいことを確認します。

```ruby:spec/controllers/users_controller_spec.rb
require 'rails_helper'

RSpec.describe UsersController, type: :controller do
  describe "GET #index" do
    let!(:user) { User.create!({name: 'Taro'}) }
    it "returns a success response" do
      get :index, as: :json
      expect(response).to be_successful
      expect(response.parsed_body).not_to be_kind_of(String)
      expect(response.parsed_body).to be_kind_of(Array)
      expect(response.parsed_body.first['name']).to eq(user.name)
    end
  end
end
```

# rspec を実行する

Rails 6 ではエラーになりません。

```
$ bundle exec rspec spec/controllers/users_controller_spec.rb
.

Finished in 0.02378 seconds (files took 0.80378 seconds to load)
1 example, 0 failures
```

Rails 5 ではエラーになります。 parsed_body の結果が文字列のままであることがわかります。

```
$ bundle exec rspec spec/controllers/users_controller_spec.rb
F

Failures:

  1) UsersController GET #index returns a success response
     Failure/Error: expect(response.parsed_body).not_to be_kind_of(String)
       expected "[{\"id\":43,\"name\":\"Taro\",\"created_at\":\"2019-08-12T14:23:52.388Z\",\"updated_at\":\"2019-08-12T14:23:52.388Z\"}]" not to be a kind of String
     # ./spec/controllers/users_controller_spec.rb:9:in `block (3 levels) in <top (required)>'

Finished in 0.0172 seconds (files took 0.87739 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/controllers/users_controller_spec.rb:6 # UsersController GET #index returns a success response'`
```

# request spec だと

以下のような request spec で試したところ、 Rails 5 でも Rails 6 でも エラーになりませんでした。

```spec/requests/users_spec.rb
require 'rails_helper'

RSpec.describe "Users", type: :request do
  describe "GET /users" do
    let!(:user) { User.create(name: 'Taro') }
    it "returns a success response" do
      get users_path, as: :json
      expect(response).to have_http_status(200)
      expect(response.parsed_body).not_to be_kind_of(String)
      expect(response.parsed_body).to be_kind_of(Array)
      expect(response.parsed_body.first['name']).to eq(user.name)
    end
  end
end
```

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try074_parsed_body


# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Allow using parsed_body in ActionController::TestCase](https://github.com/rails/rails/pull/34717)