diff --git a/app/helpers/errors_helper.rb b/app/helpers/errors_helper.rb new file mode 100644 index 000000000..e9dd015d5 --- /dev/null +++ b/app/helpers/errors_helper.rb @@ -0,0 +1,19 @@ +module ErrorsHelper + def error_title(code) + case code + when 404 then "ページが見つかりませんでした... 🥺💦" + when 422 then "リクエストが処理できませんでした… 😢" + when 500 then "予期しないエラーが発生しました 😵‍💫" + else "予期せぬエラーが発生しました…😵" + end + end + + def error_desc(code) + case code + when 404 then "ページが削除された可能性があります 🤔💭" + when 422 then "入力内容に誤りがあるか、リクエストが正しく送信されなかった可能性があります。" + when 500 then "申し訳ありません。サーバーで問題が発生しています。" + else "改善されない場合は、お手数ですがエラー報告をお願いいたします🙇‍♀️" + end + end +end diff --git a/app/views/errors/bad_request.html.erb b/app/views/errors/bad_request.html.erb index 1c64ebeb6..52a692260 100644 --- a/app/views/errors/bad_request.html.erb +++ b/app/views/errors/bad_request.html.erb @@ -1,39 +1 @@ -<% provide(:title, "ページが見つかりませんでした... 🥺💦") %> -<% provide(:desc, "ページが削除された可能性があります 🤔💭") %> - -
- -

CoderDojo Japan

-

子どものためのプログラミング道場

-
-
- -
-

- ページが見つかりませんでした... 🥺💦 -

-

- ページが削除された可能性があります 🤔💭 -
-

-

- フィードバックなどあれば info@coderdojo.jp にメールしていただくか、 -
- もしくは - GitHub Issue - に書いていただけると嬉しいです (>人< )✨ -

-
- -
-
-

- 🐣 最近の情報発信 -

-
-
- -
- -
- +<%= render template: "errors/show", locals: { status_code: 400 } %> diff --git a/app/views/errors/forbidden.html.erb b/app/views/errors/forbidden.html.erb index c9854724a..b48a4db17 100644 --- a/app/views/errors/forbidden.html.erb +++ b/app/views/errors/forbidden.html.erb @@ -1,38 +1 @@ -<% provide(:title, "403 Forbidden エラー 🚧 🏗") %> -<% provide(:desc, "アクセス権限が無いか削除された可能性があります 🤔💭") %> - -
- -

CoderDojo Japan

-

子どものためのプログラミング道場

-
-
- -
-

- アクセスできないページのため表示できませんでした 🚧 🏗 -

-

- ログインし直すことで解決する可能性があります 🤔💭 -
-

-

- フィードバックなどあれば info@coderdojo.jp にメールしていただくか、 -
- もしくは - GitHub Issue - に書いていただけると嬉しいです (>人< )✨ -

-
- -
-
-

- 🐣 最近の情報発信 -

-
-
- -
- -
\ No newline at end of file +<%= render template: "errors/show", locals: { status_code: 403 } %> diff --git a/app/views/errors/internal_server_error.html.erb b/app/views/errors/internal_server_error.html.erb new file mode 100644 index 000000000..9fb2f736e --- /dev/null +++ b/app/views/errors/internal_server_error.html.erb @@ -0,0 +1 @@ +<%= render template: "errors/show", locals: { status_code: 500 } %> diff --git a/app/views/errors/internal_server_error.json.jbuilder b/app/views/errors/internal_server_error.json.jbuilder deleted file mode 100644 index 46a32f671..000000000 --- a/app/views/errors/internal_server_error.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.error_message "We're sorry, but something went wrong." diff --git a/app/views/errors/not_found.html.erb b/app/views/errors/not_found.html.erb index 2cd2898ed..c973d34cd 100644 --- a/app/views/errors/not_found.html.erb +++ b/app/views/errors/not_found.html.erb @@ -1,38 +1 @@ -<% provide(:title, "ページが見つかりませんでした... 🥺💦") %> -<% provide(:desc, "ページが削除された可能性があります 🤔💭") %> - -
- -

CoderDojo Japan

-

子どものためのプログラミング道場

-
-
- -
-

- ページが見つかりませんでした... 🥺💦 -

-

- ページが削除された可能性があります 🤔💭 -
-

-

- フィードバックなどあれば info@coderdojo.jp にメールしていただくか、 -
- もしくは - GitHub Issue - に書いていただけると嬉しいです (>人< )✨ -

-
- -
-
-

- 🐣 最近の情報発信 -

-
-
- -
- -
+<%= render template: "errors/show", locals: { status_code: 404 } %> diff --git a/app/views/errors/not_found.json.jbuilder b/app/views/errors/not_found.json.jbuilder deleted file mode 100644 index a323a2abe..000000000 --- a/app/views/errors/not_found.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.error_message "The page you were looking for doesn't exist. You may have mistyped the address or the page may have moved." diff --git a/app/views/errors/show.html.erb b/app/views/errors/show.html.erb new file mode 100644 index 000000000..39f97a939 --- /dev/null +++ b/app/views/errors/show.html.erb @@ -0,0 +1,53 @@ +<%# The status_code local variable is passed from the parent template %> +<% title = error_title(status_code) %> +<% desc = error_desc(status_code) %> + +<% provide(:title, title) %> +<% provide(:desc, desc) %> + +
+ +

CoderDojo Japan

+

子どものためのプログラミング道場

+
+
+ +
+

<%= title %>

+

+ <%= desc %> +
+

+

+ フィードバックなどあれば info@coderdojo.jp にメールしていただくか、 +
+ もしくは + + GitHub Issue + + に書いていただけると嬉しいです (>人< )✨ +

+
+ +
+
+

+ + 🐣 最近の情報発信 + +

+
+
+ +
+ +
diff --git a/app/views/errors/unprocessable_content.html.erb b/app/views/errors/unprocessable_content.html.erb new file mode 100644 index 000000000..895be0baf --- /dev/null +++ b/app/views/errors/unprocessable_content.html.erb @@ -0,0 +1 @@ +<%= render template: "errors/show", locals: { status_code: 422 } %> diff --git a/app/views/errors/unprocessable_entity.json.jbuilder b/app/views/errors/unprocessable_entity.json.jbuilder deleted file mode 100644 index 81302a2a0..000000000 --- a/app/views/errors/unprocessable_entity.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.error_message "The change you wanted was rejected. Maybe you tried to change something you didn't have access to." diff --git a/config/environments/production.rb b/config/environments/production.rb index ce610264c..50c92b542 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -12,6 +12,9 @@ # Full error reports are disabled. config.consider_all_requests_local = false + # 本番環境では例外を自前ルーティングへ + config.exceptions_app = self.routes + # Turn on fragment caching in view templates. config.action_controller.perform_caching = true diff --git a/config/environments/test.rb b/config/environments/test.rb index e0f4be7d9..09ca29a17 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -22,6 +22,9 @@ config.consider_all_requests_local = true config.cache_store = :null_store + # テスト環境でも例外を自前ルーティングへ + config.exceptions_app = self.routes + # Render exception templates for rescuable exceptions and raise for other exceptions. config.action_dispatch.show_exceptions = :rescuable diff --git a/config/initializers/rambulance.rb b/config/initializers/rambulance.rb index 47de0907d..2b186e810 100644 --- a/config/initializers/rambulance.rb +++ b/config/initializers/rambulance.rb @@ -29,9 +29,10 @@ # If Rambulance receives an exception that is not listed here, it'll render # the internal server error template and return 500 as http status. config.rescue_responses = { - ActionController::RoutingError => :not_found, - AbstractController::ActionNotFound => :not_found, - ActionController::BadRequest => :bad_request, + "ActionController::RoutingError" => :not_found, + "AbstractController::ActionNotFound" => :not_found, + "ActionController::BadRequest" => :bad_request, + "ActionController::InvalidAuthenticityToken" => :unprocessable_entity, # "ActiveRecord::RecordNotUnique" => :unprocessable_entity, # "CanCan::AccessDenied" => :forbidden, diff --git a/config/routes.rb b/config/routes.rb index a999d47cb..a113fce34 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,6 +2,11 @@ # For details on the DSL available within this file, # see http://guides.rubyonrails.org/routing.html + # Rambulance を開発/テスト環境でのみマウント + if Rails.env.development? || Rails.env.test? + mount Rambulance::Engine => "/" + end + root "home#show" # Render legal documents by using Keiyaku CSS @@ -105,4 +110,10 @@ # Check development sent emails mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development? + + # Rambulance がキャッチする /404, /422, /500 + match "/404", to: Rambulance::Engine, via: :all, defaults: { status_code: 404 } + match "/422", to: Rambulance::Engine, via: :all, defaults: { status_code: 422 } + match "/500", to: Rambulance::Engine, via: :all, defaults: { status_code: 500 } + end diff --git a/spec/requests/errors_spec.rb b/spec/requests/errors_spec.rb index d32860644..2c3bee779 100644 --- a/spec/requests/errors_spec.rb +++ b/spec/requests/errors_spec.rb @@ -1,15 +1,64 @@ require 'rails_helper' -RSpec.describe "Errors", type: :request do +RSpec.describe 'Errors', type: :request do include Rambulance::TestHelper + include ErrorsHelper - describe "Error requests" do - it 'should render a corresponding error page' do + before do + # テスト用のルーティングを直接定義 + Rails.application.routes.draw do + get '/trigger_400', to: ->(env) { raise ActionController::BadRequest } + get '/trigger_422', to: ->(env) { raise ActionController::InvalidAuthenticityToken } + get '/trigger_500', to: ->(env) { raise 'This is a test 500 error' } + end + + # ビューのレンダリングをスタブして、レイアウト起因のエラーを回避 + allow_any_instance_of(Rambulance::ExceptionsApp).to receive(:render).and_wrap_original do |m, *args| + options = args.last.is_a?(Hash) ? args.pop : {} + m.call(*args, **options.merge(layout: false)) + end + end + + after do + # テスト後に追加したルーティングを元に戻す + Rails.application.reload_routes! + end + + describe 'Error requests' do + it 'renders the 404 error page' do with_exceptions_app do + # どのルーティングにもマッチしないパスをリクエスト get '/does_not_exist' end + expect(response.status).to eq(404) + expect(response.body).to include(error_title(404)) + expect(response.body).to include(error_desc(404)) + end - assert_equal 404, response.status + it 'renders the 422 error page' do + with_exceptions_app do + get '/trigger_422' + end + expect(response.status).to eq(422) + expect(response.body).to include(error_title(422)) + expect(response.body).to include(error_desc(422)) + end + + it 'renders the 500 error page' do + with_exceptions_app do + get '/trigger_500' + end + expect(response.status).to eq(500) + expect(response.body).to include(error_title(500)) + expect(response.body).to include(error_desc(500)) + end + it 'renders the 400 error page' do + with_exceptions_app do + get '/trigger_400' + end + expect(response.status).to eq(400) + expect(response.body).to include(error_title(400)) + expect(response.body).to include(error_desc(400)) end end end