Rails APIモードでuninitialized constant Rack::Cors (NameError)
というエラーに遭遇したので原因と対処法をまとめます。
バージョン
- Ruby 3.2.2
- Rails 7.1.2
記事の信頼性
- ぼくは独学で未経験から従業員300名以上の自社開発企業へ転職しました。
- 実務ではVue.jsとRailsを毎日書いています。
- 初心者や駆け出しエンジニアがつまづくポイントも身をもってよく理解しています。
問題
↑の画面が表示されたので「環境構築が完了!」と思い、モデルを作成するために以下のコマンドを実行したところ、uninitialized constant Rack::Cors (NameError)
というエラーが発生しました(モデルの内容は仮名)
$ docker compose -f compose-dev.yaml run --rm web rails g model Question title:string description:string
[+] Running 1/0
✔ Container quiz-app-api-db-1 Running 0.0s
/quiz-app-api/config/initializers/cors.rb:8:in `<main>': uninitialized constant Rack::Cors (NameError)
Rails.application.config.middleware.insert_before 0, Rack::Cors do
解決方法
CORSの設定をしていないことが原因でした。
捕捉:CORSとは?
CORS(Cross-Origin Resource Sharing)は、「オリジン間リソース共有」と訳されます。異なるWebサイト(オリジン)からのリクエストを許可するための仕組みです。今回の場合、Rails APIのオリジンはlocalhost:3000
なので、それ以外(localhost:5173
など)のオリジンからのリクエストを受け入れるにはCORSを設定してリクエストを許可する必要があります。
このエラーは以下の2ステップで解決です。
- gemのインストール
config/initializers/cors.rb
の設定
1. gemのインストール
rack-cors
というgemをインストールする必要があります。
今回はそもそもこのgemをインストールしていなかったのでエラーが発生していました、、。
環境構築が終わった時点だとこのgemはコメントアウトされているので、外しましょう。
source "https://rubygems.org"
ruby "3.2.2"
gem "rails", "~> 7.1.2"
gem "mysql2", "~> 0.5"
gem "puma", ">= 5.0"
gem "tzinfo-data", platforms: %i[ windows jruby ]
gem "bootsnap", require: false
# コメントアウトを外す
gem "rack-cors"
group :development, :test do
gem "debug", platforms: %i[ mri windows ]
end
コメントアウトを外したら、Gemfileを書き換えたことになるので再度Dockerfileをビルドします。
$ docker compose -f compose-dev.yaml build
完了したら次のコマンドを実行して、たしかにrack-cors
がインストールされていることを確認してください。
$ docker compose -f compose-dev.yaml run --rm web bundle info rack-cors
[+] Running 1/0
✔ Container quiz-app-api-db-1 Running 0.0s
* rack-cors (2.0.1)
Summary: Middleware for enabling Cross-Origin Resource Sharing in Rack apps
Homepage: https://github.com/cyu/rack-cors
Path: /usr/local/bundle/gems/rack-cors-2.0.1
2. config/initializers/cors.rb
の設定
次にconfig/initializers/cors.rb
に記述を追加します。
※これをやらなくてもモデル生成コマンド自体は成功すると思います。でもどうせ必要になる設定なのでこのタイミングで済ませちゃいましょう。
# Be sure to restart your server when you modify this file.
# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin Ajax requests.
# Read more: https://github.com/cyu/rack-cors
# 以下のコメントアウトを外す
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
# このAPIを呼び出すフロントエンド側のドメインを指定
origins "http://localhost:5173"
resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
これで再度モデル作成のコマンドを実行してみましょう。
$ docker compose -f compose-dev.yaml run --rm web rails g model Question title:string description:string
[+] Running 1/0
✔ Container quiz-app-api-db-1 Running 0.0s
invoke active_record
create db/migrate/20240107123040_create_question.rb
create app/models/question.rb
invoke test_unit
create test/models/question_test.rb
create test/fixtures/question.yml
無事にモデルファイルやマイグレーションファイルなどが生成されました。
おわりに
転職のためにポートフォリオを作っていたときはCORSの意味を全く理解せずにこの設定をしていました。
しかしウェブ・セキュリティ基礎試験(徳丸基礎試験)を受験したことで、しっかりとCORSの内容を把握した上で実装に取り組めました。
参考:【受験の価値あり】ウェブ・セキュリティ基礎試験(徳丸基礎試験)の勉強法
コメント