From 09d9bc836913263c22fc434d1f724410a0544b22 Mon Sep 17 00:00:00 2001 From: tomoka Date: Thu, 9 Oct 2025 07:44:54 +0900 Subject: [PATCH 1/6] =?UTF-8?q?ChecksController=E5=86=85=E3=81=AEnewspaper?= =?UTF-8?q?=E3=82=92ActiveSupport::Notifications=E3=81=AB=E7=BD=AE?= =?UTF-8?q?=E3=81=8D=E6=8F=9B=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 過去のissue対応での置き換え漏れを修正 --- app/controllers/checks_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/checks_controller.rb b/app/controllers/checks_controller.rb index d290d19d507..b9e72e1ee06 100644 --- a/app/controllers/checks_controller.rb +++ b/app/controllers/checks_controller.rb @@ -15,7 +15,7 @@ def create @check = @checkable.checks.build(user: current_user) if @check.save - Newspaper.publish(:check_create, { check: @check }) + ActiveSupport::Notifications.instrument('check.create', check: @check) if @checkable.is_a?(Product) @checkable.change_learning_status(:complete) redirect_back(fallback_location: @checkable, notice: '提出物を合格にしました。') @@ -32,7 +32,7 @@ def destroy @checkable = @check.checkable @check.destroy - Newspaper.publish(:check_cancel, { check: @check }) + ActiveSupport::Notifications.instrument('check.cancel', check: @check) @checkable.change_learning_status(:submitted) if @checkable.is_a?(Product) redirect_back(fallback_location: @checkable) end From c5c0a6886f69b92c570eefbdc256ac44cb04f997 Mon Sep 17 00:00:00 2001 From: tomoka Date: Thu, 9 Oct 2025 07:49:05 +0900 Subject: [PATCH 2/6] =?UTF-8?q?LearningStatusUpdater=E3=81=A8=E9=87=8D?= =?UTF-8?q?=E8=A4=87=E3=81=97=E3=81=A6=E3=81=84=E3=82=8B=E5=87=A6=E7=90=86?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/checks_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/checks_controller.rb b/app/controllers/checks_controller.rb index b9e72e1ee06..197bdbe6b13 100644 --- a/app/controllers/checks_controller.rb +++ b/app/controllers/checks_controller.rb @@ -17,7 +17,6 @@ def create if @check.save ActiveSupport::Notifications.instrument('check.create', check: @check) if @checkable.is_a?(Product) - @checkable.change_learning_status(:complete) redirect_back(fallback_location: @checkable, notice: '提出物を合格にしました。') else redirect_back(fallback_location: @checkable, notice: '日報を確認済みにしました。') @@ -33,7 +32,6 @@ def destroy @check.destroy ActiveSupport::Notifications.instrument('check.cancel', check: @check) - @checkable.change_learning_status(:submitted) if @checkable.is_a?(Product) redirect_back(fallback_location: @checkable) end From 94b9dc1d8e777ee085e4e04fab5638648b7a703f Mon Sep 17 00:00:00 2001 From: tomoka Date: Sun, 12 Oct 2025 07:57:53 +0900 Subject: [PATCH 3/6] =?UTF-8?q?ChecksController=20=E3=81=AE=E4=BE=8B?= =?UTF-8?q?=E5=A4=96=E5=87=A6=E7=90=86=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 画面上の不整合が発生しないよう、チェック保存/削除とステータス更新を同一トランザクション内で実行し、 いずれかが失敗した場合はロールバックされるように変更 - サイト内通知・メール通知は、画面上の不整合が起きないため、トランザクション外での実行でも問題ないと判断 - 例外を検知できるよう、update / save を update! / save! に変更 - トランザクション完了後にコールバックを実行するため、 after_create / after_destroy を after_create_commit / after_destroy_commit に変更 --- app/controllers/checks_controller.rb | 26 ++++++++++++++++---------- app/models/check.rb | 4 ++-- app/models/product.rb | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/controllers/checks_controller.rb b/app/controllers/checks_controller.rb index 197bdbe6b13..aca797f10a0 100644 --- a/app/controllers/checks_controller.rb +++ b/app/controllers/checks_controller.rb @@ -14,14 +14,14 @@ def create @check = @checkable.checks.build(user: current_user) - if @check.save - ActiveSupport::Notifications.instrument('check.create', check: @check) - if @checkable.is_a?(Product) - redirect_back(fallback_location: @checkable, notice: '提出物を合格にしました。') - else - redirect_back(fallback_location: @checkable, notice: '日報を確認済みにしました。') + begin + Check.transaction do + @check.save! + ActiveSupport::Notifications.instrument('check.create', check: @check) end - else + notice = @checkable.is_a?(Product) ? '提出物を合格にしました。' : '日報を確認済みにしました。' + redirect_back(fallback_location: @checkable, notice:) + rescue StandardError redirect_back(fallback_location: @checkable, alert: 'エラーが発生しました。') end end @@ -30,9 +30,15 @@ def destroy @check = Check.find(params[:id]) @checkable = @check.checkable - @check.destroy - ActiveSupport::Notifications.instrument('check.cancel', check: @check) - redirect_back(fallback_location: @checkable) + begin + Check.transaction do + @check.destroy! + ActiveSupport::Notifications.instrument('check.cancel', check: @check) + end + redirect_back(fallback_location: @checkable) + rescue StandardError + redirect_back(fallback_location: @checkable, alert: 'エラーが発生しました。') + end end private diff --git a/app/models/check.rb b/app/models/check.rb index 006cda209e7..97452f79aaa 100644 --- a/app/models/check.rb +++ b/app/models/check.rb @@ -3,8 +3,8 @@ class Check < ApplicationRecord belongs_to :user belongs_to :checkable, polymorphic: true - after_create CheckCallbacks.new - after_destroy CheckCallbacks.new + after_create_commit -> { CheckCallbacks.new.after_create(self) } + after_destroy_commit -> { CheckCallbacks.new.after_destroy(self) } alias sender user validates :user_id, uniqueness: { scope: %i[checkable_id checkable_type] } diff --git a/app/models/product.rb b/app/models/product.rb index 8512b24c529..c409768026d 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -96,7 +96,7 @@ def change_learning_status(status) user_id: user.id, practice_id: practice.id ) - learning.update(status:) + learning.update!(status:) end # nilの場合あり From d5d4bee5f30fb52a38669117f697186a74ad87b4 Mon Sep 17 00:00:00 2001 From: tomoka Date: Mon, 13 Oct 2025 10:38:33 +0900 Subject: [PATCH 4/6] =?UTF-8?q?API::ChecksController=E3=81=AE=E4=BE=8B?= =?UTF-8?q?=E5=A4=96=E5=87=A6=E7=90=86=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 画面上の不整合が発生しないよう、チェック保存/削除とステータス更新を同一トランザクション内で実行し、 いずれかが失敗した場合はロールバックされるように変更 - サイト内通知・メール通知は、画面上の不整合が起きないため、トランザクション外での実行でも問題ないと判断 - 例外を検知できるよう、destroy を destroy! に変更 --- app/controllers/api/checks_controller.rb | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/app/controllers/api/checks_controller.rb b/app/controllers/api/checks_controller.rb index 08450480392..4905288caa6 100644 --- a/app/controllers/api/checks_controller.rb +++ b/app/controllers/api/checks_controller.rb @@ -11,22 +11,28 @@ def index def create if checkable.checks.empty? - @check = Check.create!( - user: current_user, - checkable: - ) - ActiveSupport::Notifications.instrument('check.create', check: @check) - head :created + begin + Check.transaction do + @check = Check.create!(user: current_user, checkable:) + ActiveSupport::Notifications.instrument('check.create', check: @check) + end + head :created + rescue StandardError + render json: { message: 'エラーが発生しました。' } + end else render json: { message: "この#{checkable.class.model_name.human}は確認済です。" }, status: :unprocessable_entity end end def destroy - @check = Check.find(params[:id]).destroy - ActiveSupport::Notifications.instrument('check.cancel', check: @check) - + Check.transaction do + @check = Check.find(params[:id]).destroy! + ActiveSupport::Notifications.instrument('check.cancel', check: @check) + end head :no_content + rescue StandardError + render json: { message: 'エラーが発生しました。' } end private From 8d6445994271d72b11d8feff3b4b596fcc141ac6 Mon Sep 17 00:00:00 2001 From: tomoka Date: Wed, 22 Oct 2025 19:45:44 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BC=E6=99=82?= =?UTF-8?q?=E3=81=AE=E3=83=AD=E3=82=B0=E5=87=BA=E5=8A=9B=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/checks_controller.rb | 6 ++++-- app/controllers/checks_controller.rb | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/checks_controller.rb b/app/controllers/api/checks_controller.rb index 4905288caa6..0223304853b 100644 --- a/app/controllers/api/checks_controller.rb +++ b/app/controllers/api/checks_controller.rb @@ -17,7 +17,8 @@ def create ActiveSupport::Notifications.instrument('check.create', check: @check) end head :created - rescue StandardError + rescue StandardError => e + Rails.logger.error("[API::ChecksController#create] チェック作成でエラー: #{e.message}") render json: { message: 'エラーが発生しました。' } end else @@ -31,7 +32,8 @@ def destroy ActiveSupport::Notifications.instrument('check.cancel', check: @check) end head :no_content - rescue StandardError + rescue StandardError => e + Rails.logger.error("[API::ChecksController#destroy] チェック削除でエラー: #{e.message}") render json: { message: 'エラーが発生しました。' } end diff --git a/app/controllers/checks_controller.rb b/app/controllers/checks_controller.rb index aca797f10a0..425706e42ad 100644 --- a/app/controllers/checks_controller.rb +++ b/app/controllers/checks_controller.rb @@ -21,7 +21,8 @@ def create end notice = @checkable.is_a?(Product) ? '提出物を合格にしました。' : '日報を確認済みにしました。' redirect_back(fallback_location: @checkable, notice:) - rescue StandardError + rescue StandardError => e + Rails.logger.error("[ChecksController#create] チェック作成でエラー: #{e.message}") redirect_back(fallback_location: @checkable, alert: 'エラーが発生しました。') end end @@ -36,7 +37,8 @@ def destroy ActiveSupport::Notifications.instrument('check.cancel', check: @check) end redirect_back(fallback_location: @checkable) - rescue StandardError + rescue StandardError => e + Rails.logger.error("[ChecksController#destroy] チェック削除でエラー: #{e.message}") redirect_back(fallback_location: @checkable, alert: 'エラーが発生しました。') end end From 05be5d68f3b0318a59d10197c4902ff3c2bf5fd4 Mon Sep 17 00:00:00 2001 From: tomoka Date: Tue, 4 Nov 2025 07:53:03 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF?= =?UTF-8?q?=E4=BD=9C=E6=88=90=E6=99=82=E3=81=AE=E4=BE=8B=E5=A4=96=E7=99=BA?= =?UTF-8?q?=E7=94=9F=E6=99=82=E3=81=AB500=E3=82=B9=E3=83=86=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E3=82=B9=E3=82=92=E8=BF=94=E3=81=99=E3=82=88=E3=81=86?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=88=E5=89=8A=E9=99=A4=E5=87=A6=E7=90=86?= =?UTF-8?q?=E3=82=82=E4=BD=B5=E3=81=9B=E3=81=A6=E5=AF=BE=E5=BF=9C=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 例外発生時に200を返すのは不適切なため 削除処理については現状使用されていないが併せて同様の対応を実施 --- app/controllers/api/checks_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/checks_controller.rb b/app/controllers/api/checks_controller.rb index 0223304853b..8620b6efebd 100644 --- a/app/controllers/api/checks_controller.rb +++ b/app/controllers/api/checks_controller.rb @@ -19,7 +19,7 @@ def create head :created rescue StandardError => e Rails.logger.error("[API::ChecksController#create] チェック作成でエラー: #{e.message}") - render json: { message: 'エラーが発生しました。' } + render json: { message: 'エラーが発生しました。' }, status: :internal_server_error end else render json: { message: "この#{checkable.class.model_name.human}は確認済です。" }, status: :unprocessable_entity @@ -34,7 +34,7 @@ def destroy head :no_content rescue StandardError => e Rails.logger.error("[API::ChecksController#destroy] チェック削除でエラー: #{e.message}") - render json: { message: 'エラーが発生しました。' } + render json: { message: 'エラーが発生しました。' }, status: :internal_server_error end private