Rails7のgrape導入について、設定でハマった箇所をメモ

## 結論

先に結論を書くと、Rails7上環境において、 `config/applicaiton.rb` 上でオートロード設定をする必要はありません。
これを行おうとすると、後述するようにエラーが発生します。

## 周辺事実の説明

### 開発の経緯

筆者は現在、転職用のポートフォリオに対して、最初からRailsのAPIモードで開発するのではなく、後付けでAPI機能を実装する必要があった。
Rails開発環境では `grape` というgemが有名なため、導入を試みたが、動作確認まで時間を取られた。

### 公式の記載について

https://github.com/ruby-grape/grape

GitHubは上記なのだが、ここにも下記のとおりに記載がある。

> Rails < 5.2
Modify application.rb:
config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
See below for additional code that enables reloading of API changes in development.

この後にRails6以降についての補足を行っていて、そこではファイルの読み込みに関する項目がないため、公式も「6以降は設定しなくていいよ」と言っている可能性はありそうです。
残念ながらそれでは分かりにくいというのが実情です。

### 筆者のバージョン設定

```console
% ruby -v
ruby 3.2.0

% rails --version
Rails 7.0.4.3
```

## 実装テスト

手元でやり直してみましたので、手順に落とし込みます。

### rails newを実行

```console
% rails new test-app
      create
      create  README.md
      create  Rakefile
      create  ...

~省略~

% cd test-app
```

### gemをインストール

Gemfileに記載、インストールを行う。

```ruby:Gemfile
gem "grape"
```

```console
% bundle install
```

### 各種設定を行う

#### ルーティング

`config/routes.rb` 上でマウントを行う

```Ruby:config/routes.rb
Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

  mount API => '/'
end
```

#### オートローダーに対する設定

Rails6以降にオートローダーが変更したことを理由に、その対策を行う。
下記コードを該当ファイルに追記する。

```ruby:config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym 'API'
end
```

#### 問題の設定について

で、Rails7では以上の設定で終わることで正常動作するのだが、今回は下記設定を該当ファイルに追記していました。

```ruby:config/application.rb
module TestApp
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0

...
    config.paths.add File.join('app/api'), glob: File.join('**/*.rb')
    config.autoload_paths += Dir[Rails.root.join('app/api/*')]
  end
end
```

### 検証用APIを設置

#### app/api/api.rb

後に紹介する参考サイト様を見ながら、下記を配置していく。

```ruby:app/api/api.rb
class API < Grape::API
  prefix 'api'
  mount Resources::V1::Root
end
```

#### app/api/resources/v1/root.rb

バージョン管理を前提に、下記の通りにテスト用のエンドポイントを設定。

```ruby:app/api/resources/v1/root.rb
module Resources
  module V1
    class Root < Grape::API
      prefix 'api'
      version 'v1', using: :path
      format :json
      content_type :json, 'application/json;charset=UTF-8'

      get '/' do
        'test'
      end
    end
  end
end
```

他に書く場所が無いので補足しておくと、 `using: :path` を記述しないとgem側でAPIバージョニングを行わないようです。
この時、他のエラーを解決している状態でURLを叩いても、Rails上で新たに `ActionController::RoutingError` が発生します。

### 現状のまま動かしてみると…

ここで、

```console
% rails s
```

を行うと、下記エラーが発生します。

```console
`const_missing': uninitialized constant API::Resources (NameError)
```

これは繰り返し伝えているように、 `config/application.rb` 上に記述した内容を全て除去すれば正常動作を確認できます。

問題箇所のコードを消した後に、

```console
% rails s
```

を行い、ブラウザ上で動作確認を行います。

![スクリーンショット 2023-03-20 21.02.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151395/da3ea79b-4d8f-a3c4-06bb-6beda9e5cccc.png)


## 参考サイトとお礼

これを解決するに至ったのは、グレープシティ株式会社という企業様のテックブログを参考にしたことがきっかけにあります。

https://devlog.grapecity.co.jp/ruby-on-rails-web-api/

こちらの紹介ブログ記事の方は、他の先人様による導入チュートリアルとは異なり `application.rb` に関する記述がないため「もしかすると、この設定っていらないのか…？」と疑ったところ、解決への糸口を掴めました。
声が届くかどうかは分かりませんが、こちらお礼申し上げます。