From baa307a7bfa5e269d82aa77715368e0cbada7688 Mon Sep 17 00:00:00 2001 From: hirokiej <123009866+hirokiej@users.noreply.github.com> Date: Sat, 30 Aug 2025 15:56:19 +0900 Subject: [PATCH 01/56] =?UTF-8?q?=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF?= =?UTF-8?q?=E5=BE=8C=E3=81=AE=E6=97=A5=E5=A0=B1=E3=81=A8=E6=8F=90=E5=87=BA?= =?UTF-8?q?=E7=89=A9=E3=81=AB=E7=A2=BA=E8=AA=8D=E3=83=9C=E3=82=BF=E3=83=B3?= =?UTF-8?q?=E3=81=8C=E5=87=BA=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86=E4=B8=8D?= =?UTF-8?q?=E5=85=B7=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/shared/_check_actions.html.slim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/shared/_check_actions.html.slim b/app/views/shared/_check_actions.html.slim index 927998953a6..34e41540f71 100644 --- a/app/views/shared/_check_actions.html.slim +++ b/app/views/shared/_check_actions.html.slim @@ -22,8 +22,9 @@ = checkable.checker.login_name li.card-main-actions__item class=(checkable.checks.any? ? 'is-sub' : '') - - if check - = form_with url: polymorphic_path([checkable, check]), method: :delete, local: true do |f| + - checked_checkable = checkable.checks.first + - if checked_checkable + = form_with url: polymorphic_path([checkable, checked_checkable]), method: :delete, local: true do |f| - if checkable_type == 'Product' = f.submit "#{checkable_label}の合格を取り消す", class: 'card-main-actions__muted-action' - else From 7fd807c92d5d2350101ca810d68412867c077dd5 Mon Sep 17 00:00:00 2001 From: ryufuta Date: Mon, 21 Jul 2025 18:25:27 +0900 Subject: [PATCH 02/56] =?UTF-8?q?CorrectAnswerNotifier=E3=82=92newspaper?= =?UTF-8?q?=E3=81=8B=E3=82=89ActiveSupport::Notifications=E3=81=B8?= =?UTF-8?q?=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/correct_answers_controller.rb | 2 +- app/models/correct_answer_notifier.rb | 2 +- app/models/question_auto_closer.rb | 2 +- config/initializers/active_support_notifications.rb | 1 + config/initializers/newspaper.rb | 1 - 5 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/correct_answers_controller.rb b/app/controllers/api/correct_answers_controller.rb index ff2ff909a90..1b356279b83 100644 --- a/app/controllers/api/correct_answers_controller.rb +++ b/app/controllers/api/correct_answers_controller.rb @@ -8,7 +8,7 @@ def create @answer.type = 'CorrectAnswer' if @answer.save Newspaper.publish(:answer_save, { answer: @answer }) - Newspaper.publish(:correct_answer_save, { answer: @answer }) + ActiveSupport::Notifications.instrument('correct_answer.save', answer: @answer) head :ok else head :bad_request diff --git a/app/models/correct_answer_notifier.rb b/app/models/correct_answer_notifier.rb index 27fd20be16a..e421b3fc5c5 100644 --- a/app/models/correct_answer_notifier.rb +++ b/app/models/correct_answer_notifier.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class CorrectAnswerNotifier - def call(payload) + def call(_name, _started, _finished, _unique_id, payload) answer = payload[:answer] notify_correct_answer(answer) notify_to_chat(answer) diff --git a/app/models/question_auto_closer.rb b/app/models/question_auto_closer.rb index c933d609230..19792cf7568 100644 --- a/app/models/question_auto_closer.rb +++ b/app/models/question_auto_closer.rb @@ -99,7 +99,7 @@ def select_as_best_answer(close_answer) def publish_events(correct_answer) Newspaper.publish(:answer_save, { answer: correct_answer }) - Newspaper.publish(:correct_answer_save, { answer: correct_answer }) + ActiveSupport::Notifications.instrument('correct_answer.save', answer: correct_answer) end end end diff --git a/config/initializers/active_support_notifications.rb b/config/initializers/active_support_notifications.rb index 78fd7f5052e..d8c6930c52d 100644 --- a/config/initializers/active_support_notifications.rb +++ b/config/initializers/active_support_notifications.rb @@ -4,6 +4,7 @@ ActiveSupport::Notifications.subscribe('answer.create', AnswererWatcher.new) ActiveSupport::Notifications.subscribe('answer.create', AnswerNotifier.new) ActiveSupport::Notifications.subscribe('answer.create', NotifierToWatchingUser.new) + ActiveSupport::Notifications.subscribe('correct_answer.save', CorrectAnswerNotifier.new) ActiveSupport::Notifications.subscribe('event.create', EventOrganizerWatcher.new) ActiveSupport::Notifications.subscribe('regular_event.create', RegularEventOrganizerWatcher.new) sad_streak_updater = SadStreakUpdater.new diff --git a/config/initializers/newspaper.rb b/config/initializers/newspaper.rb index 6f1afea679f..ba112d2e29e 100644 --- a/config/initializers/newspaper.rb +++ b/config/initializers/newspaper.rb @@ -4,7 +4,6 @@ answer_cache_destroyer = AnswerCacheDestroyer.new Newspaper.subscribe(:answer_save, answer_cache_destroyer) Newspaper.subscribe(:answer_destroy, answer_cache_destroyer) - Newspaper.subscribe(:correct_answer_save, CorrectAnswerNotifier.new) Newspaper.subscribe(:graduation_update, GraduationNotifier.new) From ab4ac5859fb545b954e640d771e2bb6f0434cd6e Mon Sep 17 00:00:00 2001 From: ryufuta Date: Tue, 5 Aug 2025 15:41:36 +0900 Subject: [PATCH 03/56] =?UTF-8?q?GraduationNotifier=E3=82=92newspaper?= =?UTF-8?q?=E3=81=8B=E3=82=89ActiveSupport::Notifications=E3=81=B8?= =?UTF-8?q?=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/graduation_controller.rb | 2 +- app/models/graduation_notifier.rb | 2 +- config/initializers/active_support_notifications.rb | 3 ++- config/initializers/newspaper.rb | 2 -- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/controllers/graduation_controller.rb b/app/controllers/graduation_controller.rb index f2fa004c90d..8916b283644 100644 --- a/app/controllers/graduation_controller.rb +++ b/app/controllers/graduation_controller.rb @@ -9,7 +9,7 @@ class GraduationController < ApplicationController def update if @user.update(graduated_on: Date.current) Subscription.new.destroy(@user.subscription_id) if @user.subscription_id - Newspaper.publish(:graduation_update, { user: @user }) + ActiveSupport::Notifications.instrument('graduation.update', user: @user) redirect_to @redirect_url, notice: 'ユーザー情報を更新しました。' else redirect_to @redirect_url, alert: 'ユーザー情報の更新に失敗しました' diff --git a/app/models/graduation_notifier.rb b/app/models/graduation_notifier.rb index 6ee13c4eada..91ff553a82e 100644 --- a/app/models/graduation_notifier.rb +++ b/app/models/graduation_notifier.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class GraduationNotifier - def call(payload) + def call(_name, _started, _finished, _unique_id, payload) user = payload[:user] User.mentor.each do |mentor| ActivityDelivery.with(sender: user, receiver: mentor).notify(:graduated) diff --git a/config/initializers/active_support_notifications.rb b/config/initializers/active_support_notifications.rb index d8c6930c52d..91542c695e3 100644 --- a/config/initializers/active_support_notifications.rb +++ b/config/initializers/active_support_notifications.rb @@ -31,7 +31,8 @@ ActiveSupport::Notifications.subscribe('product.update', ProductUpdateNotifierForWatcher.new) ActiveSupport::Notifications.subscribe('product.update', ProductUpdateNotifierForChecker.new) ActiveSupport::Notifications.subscribe('came.comment', CommentNotifier.new) - + ActiveSupport::Notifications.subscribe('graduation.update', GraduationNotifier.new) + learning_status_updater = LearningStatusUpdater.new ActiveSupport::Notifications.subscribe('product.save', learning_status_updater) ActiveSupport::Notifications.subscribe('check.create', learning_status_updater) diff --git a/config/initializers/newspaper.rb b/config/initializers/newspaper.rb index ba112d2e29e..aa81047d496 100644 --- a/config/initializers/newspaper.rb +++ b/config/initializers/newspaper.rb @@ -5,8 +5,6 @@ Newspaper.subscribe(:answer_save, answer_cache_destroyer) Newspaper.subscribe(:answer_destroy, answer_cache_destroyer) - Newspaper.subscribe(:graduation_update, GraduationNotifier.new) - Newspaper.subscribe(:comeback_update, ComebackNotifier.new) unfinished_data_destroyer = UnfinishedDataDestroyer.new From e206393a4782e82a996b0b23d94263e7fdb25875 Mon Sep 17 00:00:00 2001 From: ryufuta Date: Tue, 5 Aug 2025 15:42:30 +0900 Subject: [PATCH 04/56] =?UTF-8?q?ComebackNotifier=E3=82=92newspaper?= =?UTF-8?q?=E3=81=8B=E3=82=89ActiveSupport::Notifications=E3=81=B8?= =?UTF-8?q?=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/comeback_controller.rb | 2 +- app/models/comeback_notifier.rb | 2 +- config/initializers/active_support_notifications.rb | 1 + config/initializers/newspaper.rb | 2 -- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/controllers/comeback_controller.rb b/app/controllers/comeback_controller.rb index abf51bd5b5d..f06543cf4c3 100644 --- a/app/controllers/comeback_controller.rb +++ b/app/controllers/comeback_controller.rb @@ -12,7 +12,7 @@ def create if @user if @user&.hibernated? @user.comeback! - Newspaper.publish(:comeback_update, { user: @user }) + ActiveSupport::Notifications.instrument('comeback.update', user: @user) @user.create_comebacked_comment redirect_to root_url, notice: '休会から復帰しました。' else diff --git a/app/models/comeback_notifier.rb b/app/models/comeback_notifier.rb index 1112ba9da18..6beefbf2f9b 100644 --- a/app/models/comeback_notifier.rb +++ b/app/models/comeback_notifier.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class ComebackNotifier - def call(payload) + def call(_name, _started, _finished, _unique_id, payload) user = payload[:user] User.admins_and_mentors.each do |admin_or_mentor| ActivityDelivery.with(sender: user, receiver: admin_or_mentor).notify(:comebacked) diff --git a/config/initializers/active_support_notifications.rb b/config/initializers/active_support_notifications.rb index 91542c695e3..84d2951c216 100644 --- a/config/initializers/active_support_notifications.rb +++ b/config/initializers/active_support_notifications.rb @@ -32,6 +32,7 @@ ActiveSupport::Notifications.subscribe('product.update', ProductUpdateNotifierForChecker.new) ActiveSupport::Notifications.subscribe('came.comment', CommentNotifier.new) ActiveSupport::Notifications.subscribe('graduation.update', GraduationNotifier.new) + ActiveSupport::Notifications.subscribe('comeback.update', ComebackNotifier.new) learning_status_updater = LearningStatusUpdater.new ActiveSupport::Notifications.subscribe('product.save', learning_status_updater) diff --git a/config/initializers/newspaper.rb b/config/initializers/newspaper.rb index aa81047d496..6dd95f1fb73 100644 --- a/config/initializers/newspaper.rb +++ b/config/initializers/newspaper.rb @@ -5,8 +5,6 @@ Newspaper.subscribe(:answer_save, answer_cache_destroyer) Newspaper.subscribe(:answer_destroy, answer_cache_destroyer) - Newspaper.subscribe(:comeback_update, ComebackNotifier.new) - unfinished_data_destroyer = UnfinishedDataDestroyer.new Newspaper.subscribe(:retirement_create, unfinished_data_destroyer) Newspaper.subscribe(:training_completion_create, unfinished_data_destroyer) From 40eaac4e72b6f87e5dd00e6a6719af46fcf6df5c Mon Sep 17 00:00:00 2001 From: tomoka Date: Fri, 5 Sep 2025 08:44:53 +0900 Subject: [PATCH 05/56] =?UTF-8?q?Events.jsx=E3=82=92=E9=9D=9EReact?= =?UTF-8?q?=E5=8C=96=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/events_controller.rb | 3 ++ app/views/events/_events.html.slim | 41 ++++++++++++++++++++++++++++ app/views/events/index.html.slim | 9 +++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 73ad532e530..ecf57e97b3e 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -1,9 +1,12 @@ # frozen_string_literal: true class EventsController < ApplicationController + PAGER_NUMBER = 20 + before_action :set_event, only: %i[edit update destroy] def index + @events = Event.with_avatar.includes(:comments, :users).order(start_at: :desc).page(params[:page]).per(PAGER_NUMBER) @upcoming_events_groups = UpcomingEvent.upcoming_events_groups end diff --git a/app/views/events/_events.html.slim b/app/views/events/_events.html.slim index e69de29bb2d..aca7e92dcbc 100644 --- a/app/views/events/_events.html.slim +++ b/app/views/events/_events.html.slim @@ -0,0 +1,41 @@ += paginate @events +ul.card-list.a-card + - @events.each do |event| + li.card-list-item + .card-list-item__inner + .card-list-item__user + = render 'users/icon', user: event.user, link_class: 'card-list-item__user-link', image_class: 'card-list-item__user-icon' + .card-list-item__rows + .card-list-item__row + .card-list-item-title + - if event.wip + .a-list-item-badge.is-wip + span + | WIP + - elsif event.ended? + .a-list-item-badge.is-ended + span + | 終了 + h2.card-list-item-title__title itemProp="name" + = link_to event.title, event_path(event), class: 'card-list-item-title__link a-text-link', itemProp: 'url' + .card-list-item__row + = link_to event.user.long_name, user_path(event.user), class: 'a-user-name' + .card-list-item__row + .card-list-item-meta + .card-list-item-meta__items + .card-list-item-meta__item + time.a-meta(datetime=event.start_at) + span.a-meta__label 開催日時 + span.a-meta__value = l event.start_at + .card-list-item-meta__item + .a-meta + | 参加者(#{event.participants.count}名 / #{event.capacity}名) + - if event.waitlist.count.positive? + .card-list-item-meta__item + .a-meta + | 補欠者(#{event.waitlist.count}名) + - if event.comments.size.positive? + .card-list-item-meta__item + .a-meta + | コメント(#{event.comments.size}) += paginate @events diff --git a/app/views/events/index.html.slim b/app/views/events/index.html.slim index d9fc08c5ba6..c2e068b79f7 100644 --- a/app/views/events/index.html.slim +++ b/app/views/events/index.html.slim @@ -23,5 +23,12 @@ .page-body .page-body__inner.has-side-nav .container.is-md - = react_component 'Events' + - if @events.empty? + .o-empty-message + .o-empty-message__icon + i.fa-regular.fa-sad-tear + p.o-empty-message__text + | 登録されている特別イベントはありません。 + - else + = render 'events/events' = render 'events/upcoming_events_groups', upcoming_events_groups: @upcoming_events_groups From 6ae0bd2b260824a281e54b9a7fd3d1b5a47f2f4f Mon Sep 17 00:00:00 2001 From: tomoka Date: Sat, 6 Sep 2025 08:15:18 +0900 Subject: [PATCH 06/56] =?UTF-8?q?Events.jsx=E3=81=AE=E9=9D=9EReact?= =?UTF-8?q?=E5=8C=96=E3=81=AB=E4=BC=B4=E3=81=84=E4=B8=8D=E8=A6=81=E3=81=A8?= =?UTF-8?q?=E3=81=AA=E3=81=A3=E3=81=9F=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB?= =?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/api/events_controller.rb | 12 ------------ app/views/api/events/_event.json.jbuilder | 8 -------- app/views/api/events/index.json.jbuilder | 2 -- config/routes/api.rb | 1 - 4 files changed, 23 deletions(-) delete mode 100644 app/controllers/api/events_controller.rb delete mode 100644 app/views/api/events/_event.json.jbuilder delete mode 100644 app/views/api/events/index.json.jbuilder diff --git a/app/controllers/api/events_controller.rb b/app/controllers/api/events_controller.rb deleted file mode 100644 index 3dbf684b646..00000000000 --- a/app/controllers/api/events_controller.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -class API::EventsController < API::BaseController - before_action :require_active_user_login - - def index - @events = Event.with_avatar - .includes(:comments, :users) - .order(start_at: :desc) - .page(params[:page]) - end -end diff --git a/app/views/api/events/_event.json.jbuilder b/app/views/api/events/_event.json.jbuilder deleted file mode 100644 index dd308c2814b..00000000000 --- a/app/views/api/events/_event.json.jbuilder +++ /dev/null @@ -1,8 +0,0 @@ -json.(event, :id, :title, :capacity, :wip, :start_at) -json.participants_count event.participants.count -json.waitlist_count event.waitlist.count -json.start_at_localized l(event.start_at) -json.comments_count event.comments.size -json.url event_url(event) -json.user event.user, partial: "api/users/user", as: :user -json.ended event.ended? diff --git a/app/views/api/events/index.json.jbuilder b/app/views/api/events/index.json.jbuilder deleted file mode 100644 index 5c4d3c80953..00000000000 --- a/app/views/api/events/index.json.jbuilder +++ /dev/null @@ -1,2 +0,0 @@ -json.events @events, partial: "api/events/event", as: :event -json.total_pages @events.total_pages diff --git a/config/routes/api.rb b/config/routes/api.rb index 508f43eed5a..70ddc5b37b2 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -72,7 +72,6 @@ end resources :products, only: %i(index show) resources :bookmarks, only: %i(index create destroy) - resources :events, only: %i(index) resources :report_templates, only: %i(create update) resources :markdown_tasks, only: %i(create) namespace :talks do From 51fcc768672e588b5ef29d6207c330038e6bdf13 Mon Sep 17 00:00:00 2001 From: tomoka Date: Sat, 6 Sep 2025 18:41:58 +0900 Subject: [PATCH 07/56] =?UTF-8?q?Events.jsx=E3=81=AE=E9=9D=9EReact?= =?UTF-8?q?=E5=8C=96=E3=81=AB=E4=BC=B4=E3=81=84=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/integration/api/events_test.rb | 15 --------------- test/system/events_test.rb | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 19 deletions(-) delete mode 100644 test/integration/api/events_test.rb diff --git a/test/integration/api/events_test.rb b/test/integration/api/events_test.rb deleted file mode 100644 index a9ed814fa97..00000000000 --- a/test/integration/api/events_test.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -require 'test_helper' - -class API::EventsTest < ActionDispatch::IntegrationTest - test 'GET /api/events.json' do - get api_events_path(format: :json) - assert_response :unauthorized - - token = create_token('kimura', 'testtest') - get api_events_path(format: :json), - headers: { 'Authorization' => "Bearer #{token}" } - assert_response :ok - end -end diff --git a/test/system/events_test.rb b/test/system/events_test.rb index e8717f69bb9..a73c37a95f2 100644 --- a/test/system/events_test.rb +++ b/test/system/events_test.rb @@ -249,7 +249,9 @@ class EventsTest < ApplicationSystemTestCase assert_text '参加登録しました' visit_with_auth events_path, 'hatsuno' - click_link '先着順のイベント' + within 'ul.card-list' do + click_link '先着順のイベント' + end accept_confirm do click_link '参加申込' end @@ -279,7 +281,9 @@ class EventsTest < ApplicationSystemTestCase assert_text '参加登録しました' visit_with_auth events_path, 'hatsuno' - click_link '補欠者のいるイベント' + within 'ul.card-list' do + click_link '補欠者のいるイベント' + end accept_confirm do click_link '補欠登録' end @@ -309,7 +313,9 @@ class EventsTest < ApplicationSystemTestCase assert_text '参加登録しました' visit_with_auth events_path, 'hatsuno' - click_link '補欠者が繰り上がるイベント' + within 'ul.card-list' do + click_link '補欠者が繰り上がるイベント' + end accept_confirm do click_link '補欠登録' end @@ -320,7 +326,9 @@ class EventsTest < ApplicationSystemTestCase end visit_with_auth events_path, 'kimura' - click_link '補欠者が繰り上がるイベント' + within 'ul.card-list' do + click_link '補欠者が繰り上がるイベント' + end accept_confirm do click_link '参加を取り消す' end From edad3cf6956b8840e295e24f8598a085b1dc06c2 Mon Sep 17 00:00:00 2001 From: tomoka Date: Sun, 7 Sep 2025 12:45:17 +0900 Subject: [PATCH 08/56] =?UTF-8?q?CodeRabbit=E3=81=AE=E6=8C=87=E6=91=98?= =?UTF-8?q?=E4=BA=8B=E9=A0=85=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/events/_events.html.slim | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/views/events/_events.html.slim b/app/views/events/_events.html.slim index aca7e92dcbc..3327ef9a11c 100644 --- a/app/views/events/_events.html.slim +++ b/app/views/events/_events.html.slim @@ -16,10 +16,12 @@ ul.card-list.a-card .a-list-item-badge.is-ended span | 終了 - h2.card-list-item-title__title itemProp="name" - = link_to event.title, event_path(event), class: 'card-list-item-title__link a-text-link', itemProp: 'url' + h2.card-list-item-title__title(itemprop='name') + = link_to event, itemprop: 'url', class: 'card-list-item-title__link a-text-link' do + = event.title .card-list-item__row - = link_to event.user.long_name, user_path(event.user), class: 'a-user-name' + = link_to user_path(event.user), class: 'a-user-name' do + = event.user.long_name .card-list-item__row .card-list-item-meta .card-list-item-meta__items From d1aa1f2807f330ba9b9a1faf21a06681482ac374 Mon Sep 17 00:00:00 2001 From: tomoka Date: Sun, 7 Sep 2025 13:49:45 +0900 Subject: [PATCH 09/56] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=AE=87=E6=89=80?= =?UTF-8?q?=E4=BB=A5=E5=A4=96=E3=81=AECodeRabbit=E3=81=AE=E6=8C=87?= =?UTF-8?q?=E6=91=98=E4=BA=8B=E9=A0=85=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/system/events_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/system/events_test.rb b/test/system/events_test.rb index a73c37a95f2..8b4af09931d 100644 --- a/test/system/events_test.rb +++ b/test/system/events_test.rb @@ -451,7 +451,7 @@ class EventsTest < ApplicationSystemTestCase assert_text 'イベントを作成しました' within 'form[name=announcement]' do assert has_field? 'announcement[title]', with: /#{event[:title]}/ - assert has_field? 'announcement[description]', with: /#{event[:desription]}/ + assert has_field? 'announcement[description]', with: /#{event[:description]}/ end end @@ -481,7 +481,7 @@ class EventsTest < ApplicationSystemTestCase assert_text 'イベントを更新しました' within 'form[name=announcement]' do assert has_field? 'announcement[title]', with: /#{event[:title]}/ - assert has_field? 'announcement[description]', with: /#{event[:desription]}/ + assert has_field? 'announcement[description]', with: /#{event[:description]}/ end end From ce41a590e1705b57cb95a8c55b11216b2ec8cb00 Mon Sep 17 00:00:00 2001 From: yokomaru Date: Sun, 14 Sep 2025 11:29:43 +0900 Subject: [PATCH 10/56] =?UTF-8?q?=E3=82=AB=E3=83=86=E3=82=B4=E3=83=AA?= =?UTF-8?q?=E3=81=AE=E4=BD=8D=E7=BD=AE=E3=82=92=E4=B8=80=E7=95=AA=E4=B8=8A?= =?UTF-8?q?=E3=81=AB=E7=A7=BB=E5=8B=95=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/admin/faqs/_form.html.slim | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/views/admin/faqs/_form.html.slim b/app/views/admin/faqs/_form.html.slim index f3216b14fc8..0607083a230 100644 --- a/app/views/admin/faqs/_form.html.slim +++ b/app/views/admin/faqs/_form.html.slim @@ -1,5 +1,15 @@ = form_with model: [:admin, faq], local: true, html: { name: 'faq' } do |f| .form__items + .form-item + = render 'errors', object: faq + label.a-form-label + | カテゴリー + .checkboxes + .checkboxes__items + - @faq_categories.each do |faq_category| + .checkboxes__item.is-radio + = f.radio_button :faq_category_id, faq_category.id, class: 'a-toggle-checkbox' + = f.label :faq_category_id, faq_category.name, value: faq_category.id .form-item = f.label :question, class: 'a-form-label' = f.text_area :question, class: 'a-text-input is-xs' @@ -14,16 +24,6 @@ .a-form-label | プレビュー .js-preview.a-long-text.is-md.markdown-form__preview - .form-item - = render 'errors', object: faq - label.a-form-label - | カテゴリー - .checkboxes - .checkboxes__items - - @faq_categories.each do |faq_category| - .checkboxes__item.is-radio - = f.radio_button :faq_category_id, faq_category.id, class: 'a-toggle-checkbox' - = f.label :faq_category_id, faq_category.name, value: faq_category.id .form-actions ul.form-actions__items li.form-actions__item.is-main From d29aa3a3b4dbec8c32f23b23e0f1433ce3b74053 Mon Sep 17 00:00:00 2001 From: yokomaru Date: Sun, 14 Sep 2025 11:33:59 +0900 Subject: [PATCH 11/56] =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=AE?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E4=BD=8D=E7=BD=AE=E3=82=92=E4=BB=96=E3=81=AE?= =?UTF-8?q?=E3=83=9A=E3=83=BC=E3=82=B8=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B?= =?UTF-8?q?=E3=81=A6=E7=A7=BB=E5=8B=95=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/admin/faqs/_form.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/faqs/_form.html.slim b/app/views/admin/faqs/_form.html.slim index 0607083a230..e62e41e20b2 100644 --- a/app/views/admin/faqs/_form.html.slim +++ b/app/views/admin/faqs/_form.html.slim @@ -1,7 +1,7 @@ = form_with model: [:admin, faq], local: true, html: { name: 'faq' } do |f| + = render 'errors', object: faq .form__items .form-item - = render 'errors', object: faq label.a-form-label | カテゴリー .checkboxes From 5d20af4167cfb48be56f5b6dd7d696906fc63763 Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Wed, 3 Sep 2025 16:33:37 +0900 Subject: [PATCH 12/56] =?UTF-8?q?Query=E3=82=AA=E3=83=96=E3=82=B8=E3=82=A7?= =?UTF-8?q?=E3=82=AF=E3=83=88=E3=81=AB=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF?= =?UTF-8?q?=E3=82=BF=E3=83=AA=E3=83=B3=E3=82=B0=20Product.self=5Fassigned?= =?UTF-8?q?=5Fno=5Freplied=5Fproduct=5Fids=E3=83=A1=E3=82=BD=E3=83=83?= =?UTF-8?q?=E3=83=89=E3=82=92=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF?= =?UTF-8?q?=E3=83=AA=E3=83=B3=E3=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/product.rb | 35 +------------ .../product_self_assigned_no_replied_query.rb | 50 +++++++++++++++++++ ...uct_self_assigned_no_replied_query_test.rb | 50 +++++++++++++++++++ 3 files changed, 101 insertions(+), 34 deletions(-) create mode 100644 app/queries/product_self_assigned_no_replied_query.rb create mode 100644 test/queries/product_self_assigned_no_replied_query_test.rb diff --git a/app/models/product.rb b/app/models/product.rb index ce7665dfcdf..bbf2b23e0b0 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -64,41 +64,8 @@ def self.add_latest_commented_at end end - # rubocop:disable Metrics/MethodLength - def self.self_assigned_no_replied_product_ids(user_id) - sql = <<~SQL - WITH last_comments AS ( - SELECT * - FROM comments AS parent - WHERE commentable_type = 'Product' AND id = ( - SELECT id - FROM comments AS child - WHERE parent.commentable_id = child.commentable_id - AND commentable_type = 'Product' - ORDER BY created_at DESC LIMIT 1 - ) - ), - self_assigned_products AS ( - SELECT products.* - FROM products - WHERE checker_id = ? - AND wip = false - ) - SELECT self_assigned_products.id - FROM self_assigned_products - LEFT JOIN last_comments ON self_assigned_products.id = last_comments.commentable_id - WHERE last_comments.id IS NULL - OR self_assigned_products.checker_id != last_comments.user_id - ORDER BY self_assigned_products.created_at DESC - SQL - Product.find_by_sql([sql, user_id]).map(&:id) - end - # rubocop:enable Metrics/MethodLength - def self.self_assigned_no_replied_products(user_id) - no_replied_product_ids = self_assigned_no_replied_product_ids(user_id) - Product.where(id: no_replied_product_ids) - .order(published_at: :asc, id: :asc) + ProductSelfAssignedNoRepliedQuery.new(user_id:).call end def self.require_assignment_products diff --git a/app/queries/product_self_assigned_no_replied_query.rb b/app/queries/product_self_assigned_no_replied_query.rb new file mode 100644 index 00000000000..7c545ad89de --- /dev/null +++ b/app/queries/product_self_assigned_no_replied_query.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +class ProductSelfAssignedNoRepliedQuery < Patterns::Query + queries Product + + private + + def initialize(relation = Product.all, user_id:) + super(relation) + @user_id = user_id + end + + def query + no_replied_product_ids = self_assigned_no_replied_product_ids + relation + .where(id: no_replied_product_ids) + .order(published_at: :asc, id: :asc) + end + + # rubocop:disable Metrics/MethodLength + def self_assigned_no_replied_product_ids + sql = <<~SQL + WITH last_comments AS ( + SELECT * + FROM comments AS parent + WHERE commentable_type = 'Product' AND id = ( + SELECT id + FROM comments AS child + WHERE parent.commentable_id = child.commentable_id + AND commentable_type = 'Product' + ORDER BY created_at DESC LIMIT 1 + ) + ), + self_assigned_products AS ( + SELECT products.* + FROM products + WHERE checker_id = ? + AND wip = false + ) + SELECT self_assigned_products.id + FROM self_assigned_products + LEFT JOIN last_comments ON self_assigned_products.id = last_comments.commentable_id + WHERE last_comments.id IS NULL + OR self_assigned_products.checker_id != last_comments.user_id + ORDER BY self_assigned_products.created_at DESC + SQL + Product.find_by_sql([sql, @user_id]).map(&:id) + end + # rubocop:enable Metrics/MethodLength +end diff --git a/test/queries/product_self_assigned_no_replied_query_test.rb b/test/queries/product_self_assigned_no_replied_query_test.rb new file mode 100644 index 00000000000..2fec4690e56 --- /dev/null +++ b/test/queries/product_self_assigned_no_replied_query_test.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'test_helper' + +class ProductSelfAssignedNoRepliedQueryTest < ActiveSupport::TestCase + test 'should return product self assigned no replied' do + mentor = users(:mentormentaro) + no_replied_product = Product.create!( + body: 'test', + user: users(:kimura), + practice: practices(:practice5), + checker_id: mentor.id, + published_at: Time.current.to_formatted_s(:db) + ) + + result = ProductSelfAssignedNoRepliedQuery.new(user_id: mentor.id).call + + assert_includes result, no_replied_product + end + + test 'should not include products where user has already replied' do + mentor = users(:mentormentaro) + + product = Product.create!( + body: 'already replied', + user: users(:kimura), + practice: practices(:practice5), + checker_id: mentor.id, + published_at: Time.current + ) + + Comment.create!( + commentable: product, + user: mentor, + description: '返信コメント' + ) + + result = ProductSelfAssignedNoRepliedQuery.new(user_id: mentor.id).call + + assert_not_includes result, product + end + + test 'should be ordered by published_at asc' do + mentor = users(:mentormentaro) + + result = ProductSelfAssignedNoRepliedQuery.new(user_id: mentor.id).call + + assert_equal result, result.sort_by(&:published_at) + end +end From 94bd5309a634af6b491589cc4511f704dc7e1efb Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Mon, 8 Sep 2025 13:16:38 +0900 Subject: [PATCH 13/56] =?UTF-8?q?self=5Fassigned=5Fno=5Freplied=5Fproduct?= =?UTF-8?q?=5Fids=E3=82=92=E3=83=86=E3=82=B9=E3=83=88=E3=81=8C=E9=80=9A?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E6=9B=B8=E3=81=8D=E6=8F=9B?= =?UTF-8?q?=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/product.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/models/product.rb b/app/models/product.rb index bbf2b23e0b0..6a81b770b8b 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -40,7 +40,10 @@ class Product < ApplicationRecord # rubocop:todo Metrics/ClassLength scope :unchecked, -> { where.not(id: Check.where(checkable_type: 'Product').pluck(:checkable_id)) } scope :unassigned, -> { where(checker_id: nil) } scope :self_assigned_product, ->(user_id) { where(checker_id: user_id) } - scope :self_assigned_and_replied_products, ->(user_id) { self_assigned_product(user_id).where.not(id: self_assigned_no_replied_product_ids(user_id)) } + scope :self_assigned_and_replied_products, lambda { |user_id| + self_assigned_product(user_id) + .where.not(id: ProductSelfAssignedNoRepliedQuery.new(user_id:).call.select(:id)) + } scope :wip, -> { where(wip: true) } scope :not_wip, -> { where(wip: false) } From 9dae3a87078d21acdfdf4e9fb16bc006603c3b0b Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Mon, 8 Sep 2025 13:23:20 +0900 Subject: [PATCH 14/56] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=81=A7?= =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E7=AE=87=E6=89=80=E3=82=92=E5=89=8A?= =?UTF-8?q?=E9=99=A4=E3=81=A8WIP=E3=82=92=E6=98=8E=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/queries/product_self_assigned_no_replied_query_test.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/queries/product_self_assigned_no_replied_query_test.rb b/test/queries/product_self_assigned_no_replied_query_test.rb index 2fec4690e56..c8359fafaf6 100644 --- a/test/queries/product_self_assigned_no_replied_query_test.rb +++ b/test/queries/product_self_assigned_no_replied_query_test.rb @@ -10,7 +10,8 @@ class ProductSelfAssignedNoRepliedQueryTest < ActiveSupport::TestCase user: users(:kimura), practice: practices(:practice5), checker_id: mentor.id, - published_at: Time.current.to_formatted_s(:db) + published_at: Time.current, + wip: false ) result = ProductSelfAssignedNoRepliedQuery.new(user_id: mentor.id).call @@ -26,7 +27,8 @@ class ProductSelfAssignedNoRepliedQueryTest < ActiveSupport::TestCase user: users(:kimura), practice: practices(:practice5), checker_id: mentor.id, - published_at: Time.current + published_at: Time.current, + wip: false ) Comment.create!( From 0c6cff0d5f00764aa15bc7e7a8d6bcc31c07c3b6 Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Mon, 8 Sep 2025 13:41:26 +0900 Subject: [PATCH 15/56] =?UTF-8?q?published=5Fat=E3=81=8C=E5=90=8C=E4=B8=80?= =?UTF-8?q?=E3=81=AE=E3=82=B1=E3=83=BC=E3=82=B9=E3=81=A7=E3=82=82=E6=9C=9F?= =?UTF-8?q?=E5=BE=85=E9=A0=86=E3=81=AB=E3=81=AA=E3=82=8B=E3=81=93=E3=81=A8?= =?UTF-8?q?=E3=82=92=E6=A4=9C=E8=A8=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/queries/product_self_assigned_no_replied_query_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/queries/product_self_assigned_no_replied_query_test.rb b/test/queries/product_self_assigned_no_replied_query_test.rb index c8359fafaf6..33f3796d64e 100644 --- a/test/queries/product_self_assigned_no_replied_query_test.rb +++ b/test/queries/product_self_assigned_no_replied_query_test.rb @@ -47,6 +47,6 @@ class ProductSelfAssignedNoRepliedQueryTest < ActiveSupport::TestCase result = ProductSelfAssignedNoRepliedQuery.new(user_id: mentor.id).call - assert_equal result, result.sort_by(&:published_at) + assert_equal(result, result.sort_by { |p| [p.published_at, p.id] }) end end From 9221f709b11c2d68d868ab975cd29312f45522ec Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Mon, 8 Sep 2025 14:15:51 +0900 Subject: [PATCH 16/56] =?UTF-8?q?ORDER=20BY=E9=83=A8=E5=88=86=E3=82=92.reo?= =?UTF-8?q?rder(nil)=E3=81=A7=E6=98=8E=E7=A4=BA=E7=9A=84=E3=81=AB=E3=82=AF?= =?UTF-8?q?=E3=83=AA=E3=82=A2=E3=81=AB=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/product.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/product.rb b/app/models/product.rb index 6a81b770b8b..8512b24c529 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -42,7 +42,7 @@ class Product < ApplicationRecord # rubocop:todo Metrics/ClassLength scope :self_assigned_product, ->(user_id) { where(checker_id: user_id) } scope :self_assigned_and_replied_products, lambda { |user_id| self_assigned_product(user_id) - .where.not(id: ProductSelfAssignedNoRepliedQuery.new(user_id:).call.select(:id)) + .where.not(id: ProductSelfAssignedNoRepliedQuery.new(user_id:).call.select(:id).reorder(nil)) } scope :wip, -> { where(wip: true) } From d32587b692880fc761954b9cac18e8f0ca22deae Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Wed, 17 Sep 2025 00:47:07 +0900 Subject: [PATCH 17/56] =?UTF-8?q?=E6=9C=80=E5=BE=8C=E3=81=AE=E3=82=B3?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=81=8C=E3=83=81=E3=82=A7=E3=83=83?= =?UTF-8?q?=E3=82=AF=E6=8B=85=E5=BD=93=E8=80=85=E6=9C=AC=E4=BA=BA=E3=81=A7?= =?UTF-8?q?=E3=81=AA=E3=81=84=E3=83=86=E3=82=B9=E3=83=88=E3=82=B1=E3=83=BC?= =?UTF-8?q?=E3=82=B9=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...uct_self_assigned_no_replied_query_test.rb | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/test/queries/product_self_assigned_no_replied_query_test.rb b/test/queries/product_self_assigned_no_replied_query_test.rb index 33f3796d64e..dd3d83c8c93 100644 --- a/test/queries/product_self_assigned_no_replied_query_test.rb +++ b/test/queries/product_self_assigned_no_replied_query_test.rb @@ -42,8 +42,62 @@ class ProductSelfAssignedNoRepliedQueryTest < ActiveSupport::TestCase assert_not_includes result, product end + test 'test should include products where last comment is not by checker' do + mentor = users(:mentormentaro) + user = users(:kimura) + + product = Product.create!( + body: 'test', + user:, + practice: practices(:practice5), + checker_id: mentor.id, + published_at: Time.current, + wip: false + ) + + Comment.create!( + commentable: product, + user:, + description: '生徒からの返信コメント' + ) + + result = ProductSelfAssignedNoRepliedQuery.new(user_id: mentor.id).call + + assert_includes result, product + end + test 'should be ordered by published_at asc' do mentor = users(:mentormentaro) + user = users(:hajime) + + time = Time.current + + Product.create!( + body: 'test', + user:, + practice: practices(:practice1), + checker_id: mentor.id, + published_at: time, + wip: false + ) + + Product.create!( + body: 'test', + user:, + practice: practices(:practice2), + checker_id: mentor.id, + published_at: time, + wip: false + ) + + Product.create!( + body: 'test', + user:, + practice: practices(:practice3), + checker_id: mentor.id, + published_at: time, + wip: false + ) result = ProductSelfAssignedNoRepliedQuery.new(user_id: mentor.id).call From 33ab4e1e5c3022daa71421ba0722a831d92d8e6f Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Wed, 17 Sep 2025 00:52:27 +0900 Subject: [PATCH 18/56] =?UTF-8?q?=E6=9C=AC=E6=96=87=E3=82=92=E4=BB=96?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=81=AE=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E3=81=A8=E5=90=88=E3=82=8F=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/queries/product_self_assigned_no_replied_query_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/queries/product_self_assigned_no_replied_query_test.rb b/test/queries/product_self_assigned_no_replied_query_test.rb index dd3d83c8c93..2160c4e74a4 100644 --- a/test/queries/product_self_assigned_no_replied_query_test.rb +++ b/test/queries/product_self_assigned_no_replied_query_test.rb @@ -23,7 +23,7 @@ class ProductSelfAssignedNoRepliedQueryTest < ActiveSupport::TestCase mentor = users(:mentormentaro) product = Product.create!( - body: 'already replied', + body: 'test', user: users(:kimura), practice: practices(:practice5), checker_id: mentor.id, From 2f4507d0de5ebd905f37afbc57fa98807d62ff5f Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Wed, 17 Sep 2025 01:10:18 +0900 Subject: [PATCH 19/56] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E5=90=8D?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/queries/product_self_assigned_no_replied_query_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/queries/product_self_assigned_no_replied_query_test.rb b/test/queries/product_self_assigned_no_replied_query_test.rb index 2160c4e74a4..85fedf7bf56 100644 --- a/test/queries/product_self_assigned_no_replied_query_test.rb +++ b/test/queries/product_self_assigned_no_replied_query_test.rb @@ -42,7 +42,7 @@ class ProductSelfAssignedNoRepliedQueryTest < ActiveSupport::TestCase assert_not_includes result, product end - test 'test should include products where last comment is not by checker' do + test 'should include products where last comment is not by checker' do mentor = users(:mentormentaro) user = users(:kimura) From 4ef74fdfdc577373178ea80f65625d0fa3626b40 Mon Sep 17 00:00:00 2001 From: karlley Date: Thu, 3 Jul 2025 07:10:27 +0900 Subject: [PATCH 20/56] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E5=90=8D?= =?UTF-8?q?=E3=81=8C=E6=97=A5=E6=9C=AC=E8=AA=9E=E3=81=AE=E3=81=9F=E3=82=81?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E5=90=8D?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/system/notification/reports_test.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/system/notification/reports_test.rb b/test/system/notification/reports_test.rb index e0394b4bc88..7fd9d8950e9 100644 --- a/test/system/notification/reports_test.rb +++ b/test/system/notification/reports_test.rb @@ -123,7 +123,7 @@ class Notification::ReportsTest < ApplicationSystemTestCase assert_no_text 'kimuraさんがはじめての日報を書きました!' end - test '複数の日報が投稿されているときは通知が飛ばない' do + test 'no notification if report already posted' do # 他のテストの通知に影響を受けないよう、テスト実行前に通知を削除する visit_with_auth '/notifications', 'muryou' click_link '全て既読にする' @@ -180,7 +180,7 @@ def assert_notify_only_at_first_published_of_report( end end - test '研修生が日報を作成し提出した時、企業のアドバイザーに通知する' do + test 'notify company advisor only on first report posted' do kensyu_login_name = 'kensyu' advisor_login_name = 'senpai' title = '研修生が日報を作成し提出した時' @@ -197,7 +197,7 @@ def assert_notify_only_at_first_published_of_report( ) end - test '初めて提出した時だけ、フォローされているユーザーに通知する' do + test 'notify follower only on first report posted' do following = Following.first followed_user_login_name = User.find(following.followed_id).login_name follower_user_login_name = User.find(following.follower_id).login_name @@ -215,7 +215,7 @@ def assert_notify_only_at_first_published_of_report( ) end - test '初めて提出した時だけ、メンション通知する' do + test 'notify mention target only on first report posted' do mention_target_login_name = 'kimura' author_login_name = 'machida' title = '初めて提出したら、' @@ -229,7 +229,7 @@ def assert_notify_only_at_first_published_of_report( ) end - test '初日報は初めて公開した時だけ通知する' do + test 'notify user only on first report posted' do check_notification_login_name = 'machida' author_login_name = 'nippounashi' title = '初めての日報を提出したら' From 9928b0b20e2c0e270a037a042583fba8d04f40a0 Mon Sep 17 00:00:00 2001 From: karlley Date: Thu, 14 Aug 2025 07:26:28 +0900 Subject: [PATCH 21/56] =?UTF-8?q?=E5=88=9D=E6=8A=95=E7=A8=BF=E3=81=AE?= =?UTF-8?q?=E3=81=BF=E3=81=A8=E3=81=84=E3=81=86=E3=83=8B=E3=83=A5=E3=82=A2?= =?UTF-8?q?=E3=83=B3=E3=82=B9=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E5=90=8D?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/system/notification/reports_test.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/system/notification/reports_test.rb b/test/system/notification/reports_test.rb index 7fd9d8950e9..ae8703c78b9 100644 --- a/test/system/notification/reports_test.rb +++ b/test/system/notification/reports_test.rb @@ -180,7 +180,7 @@ def assert_notify_only_at_first_published_of_report( end end - test 'notify company advisor only on first report posted' do + test 'notify company advisor only when report is initially posted' do kensyu_login_name = 'kensyu' advisor_login_name = 'senpai' title = '研修生が日報を作成し提出した時' @@ -197,7 +197,7 @@ def assert_notify_only_at_first_published_of_report( ) end - test 'notify follower only on first report posted' do + test 'notify follower only when report is initially posted' do following = Following.first followed_user_login_name = User.find(following.followed_id).login_name follower_user_login_name = User.find(following.follower_id).login_name @@ -215,7 +215,7 @@ def assert_notify_only_at_first_published_of_report( ) end - test 'notify mention target only on first report posted' do + test 'notify mention target only when report is initially posted' do mention_target_login_name = 'kimura' author_login_name = 'machida' title = '初めて提出したら、' @@ -229,7 +229,7 @@ def assert_notify_only_at_first_published_of_report( ) end - test 'notify user only on first report posted' do + test 'notify user only when report is initially posted' do check_notification_login_name = 'machida' author_login_name = 'nippounashi' title = '初めての日報を提出したら' From 95f31c3d4db912bf53def90c816dc5055ff68f07 Mon Sep 17 00:00:00 2001 From: karlley Date: Fri, 15 Aug 2025 06:19:55 +0900 Subject: [PATCH 22/56] =?UTF-8?q?=E5=88=9D=E6=97=A5=E5=A0=B1=E3=81=A8?= =?UTF-8?q?=E3=81=84=E3=81=86=E3=83=8B=E3=83=A5=E3=82=A2=E3=83=B3=E3=82=B9?= =?UTF-8?q?=E3=82=92=E3=83=86=E3=82=B9=E3=83=88=E5=90=8D=E3=81=AB=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/system/notification/reports_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/system/notification/reports_test.rb b/test/system/notification/reports_test.rb index ae8703c78b9..ef65e73ce26 100644 --- a/test/system/notification/reports_test.rb +++ b/test/system/notification/reports_test.rb @@ -229,7 +229,7 @@ def assert_notify_only_at_first_published_of_report( ) end - test 'notify user only when report is initially posted' do + test 'notify user only when first report is initially posted' do check_notification_login_name = 'machida' author_login_name = 'nippounashi' title = '初めての日報を提出したら' From b1d5c93e3fb3d4ddcf40be49d6423498a66b334b Mon Sep 17 00:00:00 2001 From: yokomaru Date: Mon, 15 Sep 2025 18:56:03 +0900 Subject: [PATCH 23/56] =?UTF-8?q?=E3=81=8A=E8=A9=A6=E3=81=97=E6=9C=9F?= =?UTF-8?q?=E9=96=93=E4=BD=9C=E6=88=90=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=AE?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E3=82=92=E7=A7=BB=E5=8B=95=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 管理ページヘッダーにあったボタンをお試し期間ページ内のヘッダー(`header.page-main-header`)に移動した - 移動先のクラスに合わせてボタンのCSSを`page-main-header`に変更した --- app/views/admin/campaigns/index.html.slim | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/views/admin/campaigns/index.html.slim b/app/views/admin/campaigns/index.html.slim index eded29f902d..4a1f46d3507 100644 --- a/app/views/admin/campaigns/index.html.slim +++ b/app/views/admin/campaigns/index.html.slim @@ -6,14 +6,6 @@ header.page-header .page-header__start h2.page-header__title | 管理ページ - .page-header__end - .page-header-actions - .page-header-actions__items - .page-header-actions__item - = link_to new_admin_campaign_path, class: 'a-button is-md is-secondary is-block' do - i.fa-regular.fa-plus - span - | お試し延長作成 = render 'admin/admin_page_tabs' @@ -24,6 +16,14 @@ main.page-main .page-main-header__start h1.page-main-header__title | お試し延長一覧 + .page-main-header__end + .page-main-header-actions + .page-main-header-actions__items + .page-main-header-actions__item + = link_to new_admin_campaign_path, class: 'a-button is-md is-secondary is-block' do + i.fa-regular.fa-plus + span + | お試し延長作成 hr.a-border .page-body .container.is-lg From ca87ad9c72ac1498bb819e6eb6f4380230bbade1 Mon Sep 17 00:00:00 2001 From: yokomaru Date: Sat, 20 Sep 2025 20:27:16 +0900 Subject: [PATCH 24/56] =?UTF-8?q?=E6=96=B0=E8=A6=8F=E4=BD=9C=E6=88=90?= =?UTF-8?q?=E3=83=9A=E3=83=BC=E3=82=B8=E4=B8=8A=E3=81=AE=E3=81=8A=E8=A9=A6?= =?UTF-8?q?=E3=81=97=E5=BB=B6=E9=95=B7=E4=B8=80=E8=A6=A7=E3=83=9C=E3=82=BF?= =?UTF-8?q?=E3=83=B3=E3=81=AB=E9=81=A9=E7=94=A8=E3=81=99=E3=82=8BCSS?= =?UTF-8?q?=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 他のお試し延長画面(edit/index)に合わせて、`header.page-main-header`内に配置されているボタンに適用するCSSは`page-main-header-actions`に統一する --- app/views/admin/campaigns/new.html.slim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/admin/campaigns/new.html.slim b/app/views/admin/campaigns/new.html.slim index eec3b19ac99..241e82630ed 100644 --- a/app/views/admin/campaigns/new.html.slim +++ b/app/views/admin/campaigns/new.html.slim @@ -17,9 +17,9 @@ main.page-main h1.page-main-header__title | お試し延長作成 .page-main-header__end - .page-header-actions - .page-header-actions__items - .page-header-actions__item + .page-main-header-actions + .page-main-header-actions__items + .page-main-header-actions__item = link_to admin_campaigns_path, class: 'a-button is-md is-secondary is-block is-back' do | お試し延長一覧 hr.a-border From 1894d14a23ff9273dfdd525c96e72a5af36f58de Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Thu, 31 Jul 2025 17:44:16 +0900 Subject: [PATCH 25/56] =?UTF-8?q?Refactor:=20Patterns::Query=E3=81=AB?= =?UTF-8?q?=E5=90=88=E3=82=8F=E3=81=9B=E3=81=9F=E3=82=AF=E3=82=A8=E3=83=AA?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=81=AE=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF?= =?UTF-8?q?=E3=82=BF=E3=83=AA=E3=83=B3=E3=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/grass.rb | 40 +--------------- app/queries/grass_learning_time_query.rb | 59 ++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 39 deletions(-) create mode 100644 app/queries/grass_learning_time_query.rb diff --git a/app/models/grass.rb b/app/models/grass.rb index 676877b3aa7..237820f43ae 100644 --- a/app/models/grass.rb +++ b/app/models/grass.rb @@ -1,45 +1,7 @@ # frozen_string_literal: true class Grass - # rubocop:disable Metrics/MethodLength def self.times(user, end_date) - start_date = end_date.prev_year.sunday - sql = <<~SQL - WITH series AS ( - SELECT - date - FROM - generate_series(:start_date::DATE, :end_date, '1 day') AS series(date) - ), - summary AS ( - SELECT - reported_on AS date, - EXTRACT(epoch FROM SUM(finished_at - started_at)) / 60 / 60 AS total_hour - FROM - learning_times JOIN reports ON learning_times.report_id = reports.id - WHERE - reports.user_id = :user_id - GROUP BY - reported_on - ORDER BY - reported_on - ) - SELECT - series.date AS date, - CASE - WHEN summary.total_hour > 6 THEN 4 - WHEN 6 >= summary.total_hour AND summary.total_hour > 4 THEN 3 - WHEN 4 >= summary.total_hour AND summary.total_hour > 2 THEN 2 - WHEN 2 >= summary.total_hour AND summary.total_hour > 0 THEN 1 - ELSE 0 - END AS velocity - FROM - series - LEFT JOIN - summary ON series.date = summary.date - SQL - - LearningTime.find_by_sql([sql, { start_date:, end_date:, user_id: user.id }]) + GrassLearningTimeQuery.call(user, end_date) end - # rubocop:enable Metrics/MethodLength end diff --git a/app/queries/grass_learning_time_query.rb b/app/queries/grass_learning_time_query.rb new file mode 100644 index 00000000000..0650d8c185c --- /dev/null +++ b/app/queries/grass_learning_time_query.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +class GrassLearningTimeQuery < Patterns::Query + queries LearningTime + + def initialize(user, end_date, relation = LearningTime.all) + super(relation) + @user = user + @end_date = end_date + @start_date = end_date.prev_year.sunday + end + + private + + def query + relation + .from("(#{compiled_sql}) AS grass_data") + .select(:date, :velocity) + end + + def compiled_sql + ActiveRecord::Base.send(:sanitize_sql_array, [sql_template, sql_params]) + end + + def sql_template + <<~SQL + WITH series AS ( + SELECT date FROM generate_series(:start_date::DATE, :end_date, '1 day') AS series(date) + ), summary AS ( + SELECT + reported_on AS date, + EXTRACT(epoch FROM SUM(finished_at - started_at)) / 60 / 60 AS total_hour + FROM learning_times + JOIN reports ON learning_times.report_id = reports.id + WHERE reports.user_id = :user_id + GROUP BY reported_on + ) + SELECT + series.date, + CASE + WHEN summary.total_hour > 6 THEN 4 + WHEN summary.total_hour > 4 THEN 3 + WHEN summary.total_hour > 2 THEN 2 + WHEN summary.total_hour > 0 THEN 1 + ELSE 0 + END AS velocity + FROM series + LEFT JOIN summary ON series.date = summary.date + SQL + end + + def sql_params + { + start_date: @start_date, + end_date: @end_date, + user_id: @user.id + } + end +end From 55a7555b683f0940549312138ea3e31e3984b7fa Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Mon, 4 Aug 2025 16:11:26 +0900 Subject: [PATCH 26/56] =?UTF-8?q?GrassLearningTimeQuery=E3=81=A7=E6=98=8E?= =?UTF-8?q?=E7=A4=BA=E7=9A=84=E3=81=AAstart=5Fdate=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/queries/grass_learning_time_query.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/queries/grass_learning_time_query.rb b/app/queries/grass_learning_time_query.rb index 0650d8c185c..866058d4192 100644 --- a/app/queries/grass_learning_time_query.rb +++ b/app/queries/grass_learning_time_query.rb @@ -3,11 +3,11 @@ class GrassLearningTimeQuery < Patterns::Query queries LearningTime - def initialize(user, end_date, relation = LearningTime.all) + def initialize(user, end_date, relation = LearningTime.all, start_date: nil) super(relation) @user = user @end_date = end_date - @start_date = end_date.prev_year.sunday + @start_date = start_date || end_date.prev_year.sunday end private From 685001f173b71c9837afbe2fe1b9149110c23f79 Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Mon, 4 Aug 2025 16:13:59 +0900 Subject: [PATCH 27/56] =?UTF-8?q?GrassLearningTimeQuery=E3=81=AE=E5=B9=B4?= =?UTF-8?q?=E3=81=BE=E3=81=9F=E3=81=8E=E3=83=BB=E6=9C=88=E3=81=BE=E3=81=9F?= =?UTF-8?q?=E3=81=8E=E3=83=BBvelocity=E8=A8=88=E7=AE=97=E3=81=AB=E9=96=A2?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=83=86=E3=82=B9=E3=83=88=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 --- .../queries/grass_learning_time_query_test.rb | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 test/queries/grass_learning_time_query_test.rb diff --git a/test/queries/grass_learning_time_query_test.rb b/test/queries/grass_learning_time_query_test.rb new file mode 100644 index 00000000000..d8675740168 --- /dev/null +++ b/test/queries/grass_learning_time_query_test.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +require "test_helper" + +class GrassLearningTimeQueryTest < ActiveSupport::TestCase + setup do + @user = users(:sotugyou) + + # 年末(2024-12-31)と年始(2025-01-01)にまたがる学習記録を作成 + @report1 = Report.create!( + user: @user, + reported_on: Date.new(2024, 12, 31), + title: "年末の記録", + description: "年末に勉強した内容", + emotion: :happy + ) + + LearningTime.create!( + report: @report1, + started_at: Time.zone.local(2024, 12, 31, 10), + finished_at: Time.zone.local(2024, 12, 31, 11) + ) + + @report2 = Report.create!( + user: @user, + reported_on: Date.new(2025, 1, 1), + title: "年始の記録", + description: "年始に勉強した内容", + emotion: :happy + ) + + LearningTime.create!( + report: @report2, + started_at: Time.zone.local(2025, 1, 1, 13), + finished_at: Time.zone.local(2025, 1, 1, 18) + ) + end + + test "includes learning data across year boundary" do + end_date = Date.new(2025, 1, 2) + results = GrassLearningTimeQuery.call(@user, end_date) + + # 結果の中に該当日が含まれていて、それぞれのvelocityが正しいかを確認 + result_by_date = results.index_by{ |r| r.date.to_date } + + assert_includes result_by_date, Date.new(2024, 12, 31) + assert_equal 1, result_by_date[Date.new(2024, 12, 31)].velocity + + assert_includes result_by_date, Date.new(2025, 1, 1) + assert_equal 3, result_by_date[Date.new(2025, 1, 1)].velocity + end + + test "calculates velocity based on total learning time for the same day" do + report = Report.create!( + user: @user, + reported_on: Date.new(2025, 1, 3), + title: "同日の複数記録", + description: "午前と午後に勉強", + emotion: :happy + ) + + LearningTime.create!( + report: report, + started_at: Time.zone.local(2025, 1, 3, 9), + finished_at: Time.zone.local(2025, 1, 3, 11) + ) + + LearningTime.create!( + report: report, + started_at: Time.zone.local(2025, 1, 3, 13), + finished_at: Time.zone.local(2025, 1, 3, 16) + ) + + start_date = Date.new(2025, 1, 3) + end_date = Date.new(2025, 1, 3) + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date: start_date).call + result_by_date = results.index_by{ |r| r.date.to_date } + + assert_equal 3, result_by_date[Date.new(2025, 1, 3)].velocity + end + + test "returns velocity 0 for dates with no learning data" do + # 2025-01-04 に何も記録しない + start_date = Date.new(2025, 1, 4) + end_date = Date.new(2025, 1, 4) + + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date: start_date).call + result_by_date = results.index_by { |r| r.date.to_date } + + assert_equal 0, result_by_date[Date.new(2025, 1, 4)].velocity + end + + test "includes learning data across month boundary" do + report1 = Report.create!( + user: @user, + reported_on: Date.new(2025, 1, 31), + title: "1月末の記録", + description: "月末の勉強", + emotion: :happy + ) + + LearningTime.create!( + report: report1, + started_at: Time.zone.local(2025, 1, 31, 10), + finished_at: Time.zone.local(2025, 1, 31, 12) + ) + + report2 = Report.create!( + user: @user, + reported_on: Date.new(2025, 2, 1), + title: "2月初の記録", + description: "月初の勉強", + emotion: :happy + ) + + LearningTime.create!( + report: report2, + started_at: Time.zone.local(2025, 2, 1, 14), + finished_at: Time.zone.local(2025, 2, 1, 17) + ) + + start_date = Date.new(2025, 1, 31) + end_date = Date.new(2025, 2, 1) + + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date: start_date).call + result_by_date = results.index_by{ |r| r.date.to_date } + + assert_equal 1, result_by_date[Date.new(2025, 1, 31)].velocity + assert_equal 2, result_by_date[Date.new(2025, 2, 1)].velocity + end +end From 8d66c89583eeab81693e3d3c4dd0047dbed8ff7d Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Mon, 4 Aug 2025 16:52:10 +0900 Subject: [PATCH 28/56] =?UTF-8?q?Rubocop=E3=81=AE=E6=8C=87=E6=91=98?= =?UTF-8?q?=E3=81=AB=E5=BE=93=E3=81=A3=E3=81=A6=E3=82=B9=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E4=BF=AE=E6=AD=A3=EF=BC=88=E3=83=8F=E3=83=83=E3=82=B7?= =?UTF-8?q?=E3=83=A5=E8=A8=98=E6=B3=95=E3=80=81=E3=82=AF=E3=82=AA=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=81=AA=E3=81=A9=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../queries/grass_learning_time_query_test.rb | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/test/queries/grass_learning_time_query_test.rb b/test/queries/grass_learning_time_query_test.rb index d8675740168..cb2fc11e9f1 100644 --- a/test/queries/grass_learning_time_query_test.rb +++ b/test/queries/grass_learning_time_query_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "test_helper" +require 'test_helper' class GrassLearningTimeQueryTest < ActiveSupport::TestCase setup do @@ -10,8 +10,8 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase @report1 = Report.create!( user: @user, reported_on: Date.new(2024, 12, 31), - title: "年末の記録", - description: "年末に勉強した内容", + title: '年末の記録', + description: '年末に勉強した内容', emotion: :happy ) @@ -24,8 +24,8 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase @report2 = Report.create!( user: @user, reported_on: Date.new(2025, 1, 1), - title: "年始の記録", - description: "年始に勉強した内容", + title: '年始の記録', + description: '年始に勉強した内容', emotion: :happy ) @@ -36,12 +36,12 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase ) end - test "includes learning data across year boundary" do + test 'includes learning data across year boundary' do end_date = Date.new(2025, 1, 2) results = GrassLearningTimeQuery.call(@user, end_date) # 結果の中に該当日が含まれていて、それぞれのvelocityが正しいかを確認 - result_by_date = results.index_by{ |r| r.date.to_date } + result_by_date = results.index_by { |r| r.date.to_date } assert_includes result_by_date, Date.new(2024, 12, 31) assert_equal 1, result_by_date[Date.new(2024, 12, 31)].velocity @@ -50,52 +50,52 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase assert_equal 3, result_by_date[Date.new(2025, 1, 1)].velocity end - test "calculates velocity based on total learning time for the same day" do + test 'calculates velocity based on total learning time for the same day' do report = Report.create!( user: @user, reported_on: Date.new(2025, 1, 3), - title: "同日の複数記録", - description: "午前と午後に勉強", + title: '同日の複数記録', + description: '午前と午後に勉強', emotion: :happy ) LearningTime.create!( - report: report, + report:, started_at: Time.zone.local(2025, 1, 3, 9), finished_at: Time.zone.local(2025, 1, 3, 11) ) LearningTime.create!( - report: report, + report:, started_at: Time.zone.local(2025, 1, 3, 13), finished_at: Time.zone.local(2025, 1, 3, 16) ) start_date = Date.new(2025, 1, 3) end_date = Date.new(2025, 1, 3) - results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date: start_date).call - result_by_date = results.index_by{ |r| r.date.to_date } + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date:).call + result_by_date = results.index_by { |r| r.date.to_date } assert_equal 3, result_by_date[Date.new(2025, 1, 3)].velocity end - test "returns velocity 0 for dates with no learning data" do + test 'returns velocity 0 for dates with no learning data' do # 2025-01-04 に何も記録しない start_date = Date.new(2025, 1, 4) end_date = Date.new(2025, 1, 4) - results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date: start_date).call + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date:).call result_by_date = results.index_by { |r| r.date.to_date } assert_equal 0, result_by_date[Date.new(2025, 1, 4)].velocity end - test "includes learning data across month boundary" do + test 'includes learning data across month boundary' do report1 = Report.create!( user: @user, reported_on: Date.new(2025, 1, 31), - title: "1月末の記録", - description: "月末の勉強", + title: '1月末の記録', + description: '月末の勉強', emotion: :happy ) @@ -108,8 +108,8 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase report2 = Report.create!( user: @user, reported_on: Date.new(2025, 2, 1), - title: "2月初の記録", - description: "月初の勉強", + title: '2月初の記録', + description: '月初の勉強', emotion: :happy ) @@ -122,8 +122,8 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase start_date = Date.new(2025, 1, 31) end_date = Date.new(2025, 2, 1) - results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date: start_date).call - result_by_date = results.index_by{ |r| r.date.to_date } + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date:).call + result_by_date = results.index_by { |r| r.date.to_date } assert_equal 1, result_by_date[Date.new(2025, 1, 31)].velocity assert_equal 2, result_by_date[Date.new(2025, 2, 1)].velocity From 0dd9261a160d91086e3cd8d55b91edaa29753bbf Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Fri, 22 Aug 2025 13:14:41 +0900 Subject: [PATCH 29/56] =?UTF-8?q?=E5=AD=A6=E7=BF=92=E6=99=82=E9=96=93?= =?UTF-8?q?=E9=9B=86=E8=A8=88SQL=E3=82=92=E6=9C=80=E9=81=A9=E5=8C=96?= =?UTF-8?q?=EF=BC=88=E6=9C=9F=E9=96=93=E3=83=95=E3=82=A3=E3=83=AB=E3=82=BF?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=83=BB=E6=9A=97=E9=BB=99=E3=82=AD=E3=83=A3?= =?UTF-8?q?=E3=82=B9=E3=83=88=E8=A7=A3=E6=B6=88=E3=83=BBORDER=20BY?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/queries/grass_learning_time_query.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/queries/grass_learning_time_query.rb b/app/queries/grass_learning_time_query.rb index 866058d4192..c1b92332c40 100644 --- a/app/queries/grass_learning_time_query.rb +++ b/app/queries/grass_learning_time_query.rb @@ -25,7 +25,7 @@ def compiled_sql def sql_template <<~SQL WITH series AS ( - SELECT date FROM generate_series(:start_date::DATE, :end_date, '1 day') AS series(date) + SELECT date FROM generate_series(:start_date::DATE, :end_date::DATE, '1 day') AS series(date) ), summary AS ( SELECT reported_on AS date, @@ -33,6 +33,7 @@ def sql_template FROM learning_times JOIN reports ON learning_times.report_id = reports.id WHERE reports.user_id = :user_id + AND reports.reported_on BETWEEN :start_date AND :end_date GROUP BY reported_on ) SELECT @@ -46,6 +47,7 @@ def sql_template END AS velocity FROM series LEFT JOIN summary ON series.date = summary.date + ORDER BY series.date SQL end From 82d3bcd0f8056b9077464f7d6ba15edb19d3e66f Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Wed, 27 Aug 2025 15:39:25 +0900 Subject: [PATCH 30/56] =?UTF-8?q?GrassLearningTimeQuery=20=E3=81=AE=20init?= =?UTF-8?q?ialize=20=E3=82=92=E7=B0=A1=E5=8D=98=E3=81=AB=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - @start_date は常に end_date.prev_year.sunday に固定 - start_date: を使ったテストは削除 - series の期間(開始日と日数)を確認するテストを追加 --- app/queries/grass_learning_time_query.rb | 4 +- .../queries/grass_learning_time_query_test.rb | 95 +++---------------- 2 files changed, 13 insertions(+), 86 deletions(-) diff --git a/app/queries/grass_learning_time_query.rb b/app/queries/grass_learning_time_query.rb index c1b92332c40..8e105dd3a9c 100644 --- a/app/queries/grass_learning_time_query.rb +++ b/app/queries/grass_learning_time_query.rb @@ -3,11 +3,11 @@ class GrassLearningTimeQuery < Patterns::Query queries LearningTime - def initialize(user, end_date, relation = LearningTime.all, start_date: nil) + def initialize(user, end_date, relation = LearningTime.all) super(relation) @user = user @end_date = end_date - @start_date = start_date || end_date.prev_year.sunday + @start_date = end_date.prev_year.sunday end private diff --git a/test/queries/grass_learning_time_query_test.rb b/test/queries/grass_learning_time_query_test.rb index cb2fc11e9f1..7ae603c86d7 100644 --- a/test/queries/grass_learning_time_query_test.rb +++ b/test/queries/grass_learning_time_query_test.rb @@ -5,49 +5,6 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase setup do @user = users(:sotugyou) - - # 年末(2024-12-31)と年始(2025-01-01)にまたがる学習記録を作成 - @report1 = Report.create!( - user: @user, - reported_on: Date.new(2024, 12, 31), - title: '年末の記録', - description: '年末に勉強した内容', - emotion: :happy - ) - - LearningTime.create!( - report: @report1, - started_at: Time.zone.local(2024, 12, 31, 10), - finished_at: Time.zone.local(2024, 12, 31, 11) - ) - - @report2 = Report.create!( - user: @user, - reported_on: Date.new(2025, 1, 1), - title: '年始の記録', - description: '年始に勉強した内容', - emotion: :happy - ) - - LearningTime.create!( - report: @report2, - started_at: Time.zone.local(2025, 1, 1, 13), - finished_at: Time.zone.local(2025, 1, 1, 18) - ) - end - - test 'includes learning data across year boundary' do - end_date = Date.new(2025, 1, 2) - results = GrassLearningTimeQuery.call(@user, end_date) - - # 結果の中に該当日が含まれていて、それぞれのvelocityが正しいかを確認 - result_by_date = results.index_by { |r| r.date.to_date } - - assert_includes result_by_date, Date.new(2024, 12, 31) - assert_equal 1, result_by_date[Date.new(2024, 12, 31)].velocity - - assert_includes result_by_date, Date.new(2025, 1, 1) - assert_equal 3, result_by_date[Date.new(2025, 1, 1)].velocity end test 'calculates velocity based on total learning time for the same day' do @@ -71,9 +28,8 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase finished_at: Time.zone.local(2025, 1, 3, 16) ) - start_date = Date.new(2025, 1, 3) end_date = Date.new(2025, 1, 3) - results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date:).call + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all).call result_by_date = results.index_by { |r| r.date.to_date } assert_equal 3, result_by_date[Date.new(2025, 1, 3)].velocity @@ -81,51 +37,22 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase test 'returns velocity 0 for dates with no learning data' do # 2025-01-04 に何も記録しない - start_date = Date.new(2025, 1, 4) end_date = Date.new(2025, 1, 4) - - results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date:).call + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all).call result_by_date = results.index_by { |r| r.date.to_date } assert_equal 0, result_by_date[Date.new(2025, 1, 4)].velocity end - test 'includes learning data across month boundary' do - report1 = Report.create!( - user: @user, - reported_on: Date.new(2025, 1, 31), - title: '1月末の記録', - description: '月末の勉強', - emotion: :happy - ) - - LearningTime.create!( - report: report1, - started_at: Time.zone.local(2025, 1, 31, 10), - finished_at: Time.zone.local(2025, 1, 31, 12) - ) - - report2 = Report.create!( - user: @user, - reported_on: Date.new(2025, 2, 1), - title: '2月初の記録', - description: '月初の勉強', - emotion: :happy - ) - - LearningTime.create!( - report: report2, - started_at: Time.zone.local(2025, 2, 1, 14), - finished_at: Time.zone.local(2025, 2, 1, 17) - ) - - start_date = Date.new(2025, 1, 31) - end_date = Date.new(2025, 2, 1) - - results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all, start_date:).call - result_by_date = results.index_by { |r| r.date.to_date } + test 'returns series with correct start_date and length' do + # デフォルト start_date(end_date.prev_year.sunday)から end_date までの series の開始日と件数が正しいことを確認 + end_date = Date.new(2025, 1, 3) + results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all).call + dates = results.map { |r| r.date.to_date } - assert_equal 1, result_by_date[Date.new(2025, 1, 31)].velocity - assert_equal 2, result_by_date[Date.new(2025, 2, 1)].velocity + expected_start_date = end_date.prev_year.sunday + assert_equal expected_start_date, dates.first + expected_length = (end_date - expected_start_date).to_i + 1 + assert_equal expected_length, dates.size end end From 900813cebe2d1b557554fba3b30bd04ae22ab7b0 Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Fri, 5 Sep 2025 10:16:00 +0900 Subject: [PATCH 31/56] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E5=90=8D?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3:=20series=20=E3=81=8C=20end=5Fdate.?= =?UTF-8?q?prev=5Fyear.sunday=20=E3=81=8B=E3=82=89=E5=A7=8B=E3=81=BE?= =?UTF-8?q?=E3=82=8B=E3=81=93=E3=81=A8=E3=82=92=E6=98=8E=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/queries/grass_learning_time_query_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/queries/grass_learning_time_query_test.rb b/test/queries/grass_learning_time_query_test.rb index 7ae603c86d7..db2b5bba2d7 100644 --- a/test/queries/grass_learning_time_query_test.rb +++ b/test/queries/grass_learning_time_query_test.rb @@ -44,8 +44,7 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase assert_equal 0, result_by_date[Date.new(2025, 1, 4)].velocity end - test 'returns series with correct start_date and length' do - # デフォルト start_date(end_date.prev_year.sunday)から end_date までの series の開始日と件数が正しいことを確認 + test 'rreturns series from the Sunday of end_date.prev_year to end_date with correct length' do end_date = Date.new(2025, 1, 3) results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all).call dates = results.map { |r| r.date.to_date } From d4e30b9f20f6f8ea2c3483f61c29f3a38d700d86 Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Fri, 5 Sep 2025 11:13:20 +0900 Subject: [PATCH 32/56] =?UTF-8?q?reports(user=5Fid,=20reported=5Fon)=20?= =?UTF-8?q?=E3=81=AB=E3=82=A4=E3=83=B3=E3=83=87=E3=83=83=E3=82=AF=E3=82=B9?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ユニークなしの複合インデックスを追加 - 学習時間集計クエリの高速化用 --- ..._reports_user_id_reported_on_index_for_learning_time.rb | 7 +++++++ db/schema.rb | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20250905020126_add_reports_user_id_reported_on_index_for_learning_time.rb diff --git a/db/migrate/20250905020126_add_reports_user_id_reported_on_index_for_learning_time.rb b/db/migrate/20250905020126_add_reports_user_id_reported_on_index_for_learning_time.rb new file mode 100644 index 00000000000..88a7cfe80c3 --- /dev/null +++ b/db/migrate/20250905020126_add_reports_user_id_reported_on_index_for_learning_time.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddReportsUserIdReportedOnIndexForLearningTime < ActiveRecord::Migration[6.1] + def change + add_index :reports, [:user_id, :reported_on], name: "idx_reports_user_date" + end +end diff --git a/db/schema.rb b/db/schema.rb index b68008280c3..974ef5a6cea 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2025_08_20_212112) do +ActiveRecord::Schema.define(version: 2025_09_05_020126) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -783,6 +783,7 @@ t.integer "emotion" t.datetime "published_at" t.index ["created_at"], name: "index_reports_on_created_at" + t.index ["user_id", "reported_on"], name: "idx_reports_user_date" t.index ["user_id", "reported_on"], name: "index_reports_on_user_id_and_reported_on", unique: true t.index ["user_id", "title"], name: "index_reports_on_user_id_and_title", unique: true t.index ["user_id"], name: "reports_user_id" From a570196d236a4c2f0e8af5df7247d0592b9229a1 Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Fri, 5 Sep 2025 12:07:32 +0900 Subject: [PATCH 33/56] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=83=87=E3=83=83=E3=82=AF=E3=82=B9=20idx=5Freports?= =?UTF-8?q?=5Fuser=5Fdate=20=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../20250905025850_remove_redundant_index_from_reports.rb | 7 +++++++ db/schema.rb | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20250905025850_remove_redundant_index_from_reports.rb diff --git a/db/migrate/20250905025850_remove_redundant_index_from_reports.rb b/db/migrate/20250905025850_remove_redundant_index_from_reports.rb new file mode 100644 index 00000000000..7c95d98ee52 --- /dev/null +++ b/db/migrate/20250905025850_remove_redundant_index_from_reports.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class RemoveRedundantIndexFromReports < ActiveRecord::Migration[6.1] + def change + remove_index :reports, name: 'idx_reports_user_date' + end +end diff --git a/db/schema.rb b/db/schema.rb index 974ef5a6cea..4b4814deabb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2025_09_05_020126) do +ActiveRecord::Schema.define(version: 2025_09_05_025850) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -783,7 +783,6 @@ t.integer "emotion" t.datetime "published_at" t.index ["created_at"], name: "index_reports_on_created_at" - t.index ["user_id", "reported_on"], name: "idx_reports_user_date" t.index ["user_id", "reported_on"], name: "index_reports_on_user_id_and_reported_on", unique: true t.index ["user_id", "title"], name: "index_reports_on_user_id_and_title", unique: true t.index ["user_id"], name: "reports_user_id" From 4dfd6691294798e4c4eab783540921ec596b0645 Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Mon, 8 Sep 2025 11:05:14 +0900 Subject: [PATCH 34/56] =?UTF-8?q?GrassLearningTimeQuery=E3=81=AEvelocity?= =?UTF-8?q?=E8=A8=88=E7=AE=97=E3=81=A72h/4h/6h=E3=81=AE=E5=A2=83=E7=95=8C?= =?UTF-8?q?=E5=80=A4=E3=82=92=E3=83=86=E3=82=B9=E3=83=88(=E3=82=BF?= =?UTF-8?q?=E3=82=A4=E3=83=9D=E4=BF=AE=E6=AD=A3=E5=90=AB=E3=82=80=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../queries/grass_learning_time_query_test.rb | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/test/queries/grass_learning_time_query_test.rb b/test/queries/grass_learning_time_query_test.rb index db2b5bba2d7..b58b1577ea0 100644 --- a/test/queries/grass_learning_time_query_test.rb +++ b/test/queries/grass_learning_time_query_test.rb @@ -44,7 +44,7 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase assert_equal 0, result_by_date[Date.new(2025, 1, 4)].velocity end - test 'rreturns series from the Sunday of end_date.prev_year to end_date with correct length' do + test 'returns series from the Sunday of end_date.prev_year to end_date with correct length' do end_date = Date.new(2025, 1, 3) results = GrassLearningTimeQuery.new(@user, end_date, LearningTime.all).call dates = results.map { |r| r.date.to_date } @@ -54,4 +54,64 @@ class GrassLearningTimeQueryTest < ActiveSupport::TestCase expected_length = (end_date - expected_start_date).to_i + 1 assert_equal expected_length, dates.size end + + test 'velocity is 1 when total_hour is exactly 2' do + report = Report.create!( + user: @user, + reported_on: Date.new(2025, 1, 5), + title: '2時間テスト', + description: 'テスト用ダミー内容', + emotion: :happy + ) + LearningTime.create!( + report:, + started_at: Time.zone.local(2025, 1, 5, 10), + finished_at: Time.zone.local(2025, 1, 5, 12) + ) + + results = GrassLearningTimeQuery.new(@user, Date.new(2025, 1, 5)).call + result_by_date = results.index_by { |r| r.date.to_date } + + assert_equal 1, result_by_date[Date.new(2025, 1, 5)].velocity + end + + test 'velocity is 2 when total_hour is exactly 4' do + report = Report.create!( + user: @user, + reported_on: Date.new(2025, 1, 6), + title: '4時間テスト', + description: 'テスト用ダミー内容', + emotion: :happy + ) + LearningTime.create!( + report:, + started_at: Time.zone.local(2025, 1, 6, 9), + finished_at: Time.zone.local(2025, 1, 6, 13) + ) + + results = GrassLearningTimeQuery.new(@user, Date.new(2025, 1, 6)).call + result_by_date = results.index_by { |r| r.date.to_date } + + assert_equal 2, result_by_date[Date.new(2025, 1, 6)].velocity + end + + test 'velocity is 3 when total_hour is exactly 6' do + report = Report.create!( + user: @user, + reported_on: Date.new(2025, 1, 7), + title: '6時間テスト', + description: 'テスト用ダミー内容', + emotion: :happy + ) + LearningTime.create!( + report:, + started_at: Time.zone.local(2025, 1, 7, 8), + finished_at: Time.zone.local(2025, 1, 7, 14) + ) + + results = GrassLearningTimeQuery.new(@user, Date.new(2025, 1, 7)).call + result_by_date = results.index_by { |r| r.date.to_date } + + assert_equal 3, result_by_date[Date.new(2025, 1, 7)].velocity + end end From 49543e3d0ac4b8912758a15bf88ad0c685187a6e Mon Sep 17 00:00:00 2001 From: sharoa119 Date: Mon, 22 Sep 2025 10:22:23 +0900 Subject: [PATCH 35/56] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=20reports=20?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=83=87=E3=83=83=E3=82=AF=E3=82=B9=E9=96=A2?= =?UTF-8?q?=E9=80=A3=E3=83=9E=E3=82=A4=E3=82=B0=E3=83=AC=E3=83=BC=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._reports_user_id_reported_on_index_for_learning_time.rb | 7 ------- .../20250905025850_remove_redundant_index_from_reports.rb | 7 ------- 2 files changed, 14 deletions(-) delete mode 100644 db/migrate/20250905020126_add_reports_user_id_reported_on_index_for_learning_time.rb delete mode 100644 db/migrate/20250905025850_remove_redundant_index_from_reports.rb diff --git a/db/migrate/20250905020126_add_reports_user_id_reported_on_index_for_learning_time.rb b/db/migrate/20250905020126_add_reports_user_id_reported_on_index_for_learning_time.rb deleted file mode 100644 index 88a7cfe80c3..00000000000 --- a/db/migrate/20250905020126_add_reports_user_id_reported_on_index_for_learning_time.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class AddReportsUserIdReportedOnIndexForLearningTime < ActiveRecord::Migration[6.1] - def change - add_index :reports, [:user_id, :reported_on], name: "idx_reports_user_date" - end -end diff --git a/db/migrate/20250905025850_remove_redundant_index_from_reports.rb b/db/migrate/20250905025850_remove_redundant_index_from_reports.rb deleted file mode 100644 index 7c95d98ee52..00000000000 --- a/db/migrate/20250905025850_remove_redundant_index_from_reports.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class RemoveRedundantIndexFromReports < ActiveRecord::Migration[6.1] - def change - remove_index :reports, name: 'idx_reports_user_date' - end -end From ec8456dc9a38eb2b91fb09fbc4bca12803536c9b Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Mon, 22 Sep 2025 11:15:22 +0900 Subject: [PATCH 36/56] =?UTF-8?q?=E3=81=8A=E7=9F=A5=E3=82=89=E3=81=9B?= =?UTF-8?q?=E3=81=AB=E3=83=96=E3=83=83=E3=82=AF=E3=83=9E=E3=83=BC=E3=82=AF?= =?UTF-8?q?=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/announcement.rb | 1 + app/views/announcements/show.html.slim | 2 ++ test/fixtures/bookmarks.yml | 4 ++++ test/system/bookmarks_test.rb | 22 ++++++++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/app/models/announcement.rb b/app/models/announcement.rb index b4a2d8fe320..7c5cb41b154 100644 --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -7,6 +7,7 @@ class Announcement < ApplicationRecord include Reactionable include WithAvatar include Watchable + include Bookmarkable enum target: { all: 0, diff --git a/app/views/announcements/show.html.slim b/app/views/announcements/show.html.slim index 278f029a555..66e139f8186 100644 --- a/app/views/announcements/show.html.slim +++ b/app/views/announcements/show.html.slim @@ -55,6 +55,8 @@ hr.a-border .page-content-header-actions .page-content-header-actions__start = render 'watches/watch_toggle', type: @announcement.class.to_s, id: @announcement.id, watch: @announcement.watch_by(current_user) + .page-content-header-actions__action + = react_component('BookmarkButton', bookmarkableId: @announcement.id, bookmarkableType: 'Announcement') .page-content-header-actions__end .page-content-header-actions__action = link_to new_announcement_path(id: @announcement), class: 'a-button is-sm is-secondary is-block', id: 'copy' do diff --git a/test/fixtures/bookmarks.yml b/test/fixtures/bookmarks.yml index 6b983e25a93..da2b7d2eb51 100644 --- a/test/fixtures/bookmarks.yml +++ b/test/fixtures/bookmarks.yml @@ -1,3 +1,7 @@ +bookmark32: + user: kimura + bookmarkable: announcement1 (Announcement) + bookmark31: user: komagata bookmarkable: talk1 (Talk) diff --git a/test/system/bookmarks_test.rb b/test/system/bookmarks_test.rb index 62e1cebd1b9..260dd7943cd 100644 --- a/test/system/bookmarks_test.rb +++ b/test/system/bookmarks_test.rb @@ -6,6 +6,7 @@ class BookmarksTest < ApplicationSystemTestCase setup do @report = reports(:report1) @question = questions(:question1) + @announcement = announcements(:announcement1) end test 'show my bookmark report' do @@ -78,4 +79,25 @@ class BookmarksTest < ApplicationSystemTestCase visit '/current_user/bookmarks' assert_no_text @question.title end + + test 'bookmark announcement' do + visit_with_auth "/announcements/#{@announcement.id}", 'hatsuno' + find('#bookmark-button').click + assert_selector '#bookmark-button.is-active' + assert_no_selector '#bookmark-button.is-inactive' + + visit '/current_user/bookmarks' + assert_text @announcement.title + end + + test 'unbookmark announcement' do + visit_with_auth "/announcements/#{@announcement.id}", 'kimura' + assert_selector '#bookmark-button.is-active' + find('#bookmark-button').click + assert_selector '#bookmark-button.is-inactive' + assert_no_selector '#bookmark-button.is-active' + + visit '/current_user/bookmarks' + assert_no_text @announcement.title + end end From d29393c49d85f702c53f2ae755cdec259470a5ff Mon Sep 17 00:00:00 2001 From: smallmonkeykey Date: Mon, 22 Sep 2025 12:13:42 +0900 Subject: [PATCH 37/56] =?UTF-8?q?fixture=E3=81=AB=E4=BE=9D=E5=AD=98?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=81=9F=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E3=80=81=E3=83=86=E3=82=B9=E3=83=88=E5=86=85=E3=81=A7=E3=83=87?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E3=82=92=E4=BD=9C=E6=88=90=E3=81=99=E3=82=8B?= =?UTF-8?q?=E5=BD=A2=E3=81=AB=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/fixtures/bookmarks.yml | 4 ---- test/system/bookmarks_test.rb | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/test/fixtures/bookmarks.yml b/test/fixtures/bookmarks.yml index da2b7d2eb51..6b983e25a93 100644 --- a/test/fixtures/bookmarks.yml +++ b/test/fixtures/bookmarks.yml @@ -1,7 +1,3 @@ -bookmark32: - user: kimura - bookmarkable: announcement1 (Announcement) - bookmark31: user: komagata bookmarkable: talk1 (Talk) diff --git a/test/system/bookmarks_test.rb b/test/system/bookmarks_test.rb index 260dd7943cd..f2e3be15317 100644 --- a/test/system/bookmarks_test.rb +++ b/test/system/bookmarks_test.rb @@ -91,7 +91,10 @@ class BookmarksTest < ApplicationSystemTestCase end test 'unbookmark announcement' do - visit_with_auth "/announcements/#{@announcement.id}", 'kimura' + user = users(:kimura) + user.bookmarks.create!(bookmarkable: @announcement) + + visit_with_auth "/announcements/#{@announcement.id}", user.login_name assert_selector '#bookmark-button.is-active' find('#bookmark-button').click assert_selector '#bookmark-button.is-inactive' From 26e3c56b2966f94241a9e516fbf3b126a4cae331 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:37:35 +0000 Subject: [PATCH 38/56] Bump rack from 2.2.17 to 2.2.18 Bumps [rack](https://github.com/rack/rack) from 2.2.17 to 2.2.18. - [Release notes](https://github.com/rack/rack/releases) - [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md) - [Commits](https://github.com/rack/rack/compare/v2.2.17...v2.2.18) --- updated-dependencies: - dependency-name: rack dependency-version: 2.2.18 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c4bc295ba4f..de18dcdb5aa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -415,7 +415,7 @@ GEM nio4r (~> 2.0) raabro (1.4.0) racc (1.8.1) - rack (2.2.17) + rack (2.2.18) rack-cors (2.0.2) rack (>= 2.0.0) rack-dev-mark (0.8.0) From 035918469f484c54076919f33d4ed67cac273246 Mon Sep 17 00:00:00 2001 From: komagata Date: Fri, 26 Sep 2025 04:37:43 +0900 Subject: [PATCH 39/56] =?UTF-8?q?=E6=9C=AA=E7=A2=BA=E8=AA=8D=E3=81=AE?= =?UTF-8?q?=E6=97=A5=E5=A0=B1=E3=83=9A=E3=83=BC=E3=82=B8=E3=81=AEURL?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新しいURLに変わっていたのと、それがRESTfulなURLになっていなかったので 元のURLに戻しました。 --- app/controllers/reports_controller.rb | 12 +++++++++++- app/views/reports/index.html.slim | 6 +++--- config/routes/reports.rb | 3 +++ test/system/reports_practice_filter_test.rb | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 8d5e56856bd..6ddbf8a10b3 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -14,9 +14,19 @@ class ReportsController < ApplicationController # rubocop:todo Metrics/ClassLeng before_action :set_watch, only: %i[show] def index + # Backward compatibility: redirect old query param URL to the new path + return redirect_to unchecked_reports_path if params[:unchecked].present? + @reports = Report.list.page(params[:page]).per(PAGER_NUMBER) @reports = @reports.joins(:practices).where(practices: { id: params[:practice_id] }) if params[:practice_id].present? - @reports = @reports.unchecked.not_wip if params[:unchecked].present? && admin_or_mentor_login? + end + + def unchecked + return redirect_to reports_path unless admin_or_mentor_login? + + @reports = Report.list.page(params[:page]).per(PAGER_NUMBER) + @reports = @reports.unchecked.not_wip + render :index end def show diff --git a/app/views/reports/index.html.slim b/app/views/reports/index.html.slim index 39e8acdb943..8ff1a3bf33a 100644 --- a/app/views/reports/index.html.slim +++ b/app/views/reports/index.html.slim @@ -20,10 +20,10 @@ main.page-main nav.pill-nav ul.pill-nav__items li.pill-nav__item - = link_to '全て', reports_path, class: "pill-nav__item-link#{' is-active' unless params[:unchecked]}" + = link_to '全て', reports_path, class: "pill-nav__item-link#{' is-active' if action_name == 'index'}" li.pill-nav__item - = link_to '未チェック', reports_path(unchecked: true), class: "pill-nav__item-link#{' is-active' if params[:unchecked]}" - - if params[:unchecked].blank? + = link_to '未チェック', unchecked_reports_path, class: "pill-nav__item-link#{' is-active' if action_name == 'unchecked'}" + - if action_name != 'unchecked' nav.page-filter.form.pb-0 .container.is-md = form_with url: reports_path, local: true, method: :get do diff --git a/config/routes/reports.rb b/config/routes/reports.rb index a92fad36217..a1f65d0f860 100644 --- a/config/routes/reports.rb +++ b/config/routes/reports.rb @@ -2,6 +2,9 @@ Rails.application.routes.draw do resources :reports do + collection do + get :unchecked + end resources :checks, only: [:create, :destroy] end end diff --git a/test/system/reports_practice_filter_test.rb b/test/system/reports_practice_filter_test.rb index fe3c1c5dc0c..9352f069011 100644 --- a/test/system/reports_practice_filter_test.rb +++ b/test/system/reports_practice_filter_test.rb @@ -36,7 +36,7 @@ class ReportsPracticeFilterTest < ApplicationSystemTestCase end test 'practice filter is hidden when unchecked parameter is present' do - visit reports_path(unchecked: true) + visit unchecked_reports_path assert_no_selector 'select#js-choices-single-select', wait: 5 end end From 69f15f398201f6b8be63b59e3ba81693bf731897 Mon Sep 17 00:00:00 2001 From: komagata Date: Sat, 27 Sep 2025 14:47:56 +0900 Subject: [PATCH 40/56] =?UTF-8?q?markdown-it-purifier=E3=82=92=E5=A4=96?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit バッククォート内のHTMLも有効になるために色々なページが 崩れてしまう問題が多発しているため。 --- app/javascript/markdown-initializer.js | 2 -- app/javascript/textarea-initializer.js | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/javascript/markdown-initializer.js b/app/javascript/markdown-initializer.js index e5582ed58ad..f7be260a16c 100644 --- a/app/javascript/markdown-initializer.js +++ b/app/javascript/markdown-initializer.js @@ -12,7 +12,6 @@ import MarkDownItContainerMessage from 'markdown-it-container-message' import MarkDownItContainerDetails from 'markdown-it-container-details' import MarkDownItLinkAttributes from 'markdown-it-link-attributes' import MarkDownItContainerSpeak from 'markdown-it-container-speak' -import MarkdownItPurifier from 'markdown-it-purifier' import ReplaceLinkToCard from 'replace-link-to-card' import MarkDownItContainerFigure from 'markdown-it-container-figure' import MarkdownItVimeo from 'markdown-it-vimeo' @@ -62,7 +61,6 @@ export default class { md.use(MarkDownItContainerFigure) md.use(MarkdownItVimeo) md.use(MarkdownItYoutube) - md.use(MarkdownItPurifier) return md.render(text) } } diff --git a/app/javascript/textarea-initializer.js b/app/javascript/textarea-initializer.js index 72d787523bc..d42348cba10 100644 --- a/app/javascript/textarea-initializer.js +++ b/app/javascript/textarea-initializer.js @@ -17,7 +17,6 @@ import CSRF from 'csrf' import TextareaMarkdownLinkify from 'textarea-markdown-linkify' import ReplaceLinkToCard from 'replace-link-to-card' import MarkDownItContainerFigure from 'markdown-it-container-figure' -import MarkdownItPurifier from 'markdown-it-purifier' import MarkdownItVimeo from 'markdown-it-vimeo' import MarkdownItYoutube from 'markdown-it-youtube' @@ -90,8 +89,7 @@ export default class { MarkDownItContainerSpeak, MarkDownItContainerFigure, MarkdownItVimeo, - MarkdownItYoutube, - MarkdownItPurifier + MarkdownItYoutube ], markdownOptions: MarkdownOption }) From f60a1bf7aa06af710e5666d640debb4e958ed11b Mon Sep 17 00:00:00 2001 From: komagata Date: Sat, 27 Sep 2025 15:54:53 +0900 Subject: [PATCH 41/56] =?UTF-8?q?unchecked=E3=83=9A=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=81=AEcontroller=E3=82=92=E6=95=B4=E7=90=86=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reports/unchecked_controller.rb | 18 ++++++++++++++++++ app/controllers/reports_controller.rb | 11 ----------- .../home/_unchecked_report_alert.html.slim | 2 +- app/views/reports/index.html.slim | 6 +++--- config/routes/reports.rb | 6 +++--- test/system/reports_practice_filter_test.rb | 2 +- 6 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 app/controllers/reports/unchecked_controller.rb diff --git a/app/controllers/reports/unchecked_controller.rb b/app/controllers/reports/unchecked_controller.rb new file mode 100644 index 00000000000..f7dc0158f5f --- /dev/null +++ b/app/controllers/reports/unchecked_controller.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class Reports::UncheckedController < ApplicationController + PAGER_NUMBER = 25 + before_action :require_admin_or_mentor! + + def index + @reports = Report.list.page(params[:page]).per(PAGER_NUMBER) + @reports = @reports.unchecked.not_wip + render 'reports/index' + end + + private + + def require_admin_or_mentor! + redirect_to reports_path unless admin_or_mentor_login? + end +end diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 6ddbf8a10b3..ad79dd68e1e 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -14,21 +14,10 @@ class ReportsController < ApplicationController # rubocop:todo Metrics/ClassLeng before_action :set_watch, only: %i[show] def index - # Backward compatibility: redirect old query param URL to the new path - return redirect_to unchecked_reports_path if params[:unchecked].present? - @reports = Report.list.page(params[:page]).per(PAGER_NUMBER) @reports = @reports.joins(:practices).where(practices: { id: params[:practice_id] }) if params[:practice_id].present? end - def unchecked - return redirect_to reports_path unless admin_or_mentor_login? - - @reports = Report.list.page(params[:page]).per(PAGER_NUMBER) - @reports = @reports.unchecked.not_wip - render :index - end - def show @products = @report.user.products.not_wip.order(published_at: :desc) @comments = @report.comments.order(:created_at) diff --git a/app/views/home/_unchecked_report_alert.html.slim b/app/views/home/_unchecked_report_alert.html.slim index edef920300b..3fce7507492 100644 --- a/app/views/home/_unchecked_report_alert.html.slim +++ b/app/views/home/_unchecked_report_alert.html.slim @@ -7,7 +7,7 @@ .unchecked-report-alert__icon i.fa-regular.fa-triangle-exclamation .unchecked-report-alert__message - = link_to '/reports/unchecked', class: 'unchecked-report-alert__message-link' do + = link_to reports_unchecked_index_path, class: 'unchecked-report-alert__message-link' do | 未チェックの日報が strong.unchecked-report-alert__count span.unchecked-report-alert__count-number diff --git a/app/views/reports/index.html.slim b/app/views/reports/index.html.slim index 8ff1a3bf33a..7c237d54691 100644 --- a/app/views/reports/index.html.slim +++ b/app/views/reports/index.html.slim @@ -20,10 +20,10 @@ main.page-main nav.pill-nav ul.pill-nav__items li.pill-nav__item - = link_to '全て', reports_path, class: "pill-nav__item-link#{' is-active' if action_name == 'index'}" + = link_to '全て', reports_path, class: "pill-nav__item-link#{' is-active' if controller_path == 'reports'}" li.pill-nav__item - = link_to '未チェック', unchecked_reports_path, class: "pill-nav__item-link#{' is-active' if action_name == 'unchecked'}" - - if action_name != 'unchecked' + = link_to '未チェック', reports_unchecked_index_path, class: "pill-nav__item-link#{' is-active' if controller_path == 'reports/unchecked'}" + - if controller_path != 'reports/unchecked' nav.page-filter.form.pb-0 .container.is-md = form_with url: reports_path, local: true, method: :get do diff --git a/config/routes/reports.rb b/config/routes/reports.rb index a1f65d0f860..7a72dedf028 100644 --- a/config/routes/reports.rb +++ b/config/routes/reports.rb @@ -2,9 +2,9 @@ Rails.application.routes.draw do resources :reports do - collection do - get :unchecked - end resources :checks, only: [:create, :destroy] end + namespace :reports do + resources :unchecked, only: %i[index] + end end diff --git a/test/system/reports_practice_filter_test.rb b/test/system/reports_practice_filter_test.rb index 9352f069011..45e73c8b57f 100644 --- a/test/system/reports_practice_filter_test.rb +++ b/test/system/reports_practice_filter_test.rb @@ -36,7 +36,7 @@ class ReportsPracticeFilterTest < ApplicationSystemTestCase end test 'practice filter is hidden when unchecked parameter is present' do - visit unchecked_reports_path + visit reports_unchecked_index_path assert_no_selector 'select#js-choices-single-select', wait: 5 end end From f21bb0b524b85719d847c33f98903917dfbae6f9 Mon Sep 17 00:00:00 2001 From: Masaki Komagata Date: Wed, 1 Oct 2025 14:55:59 +0900 Subject: [PATCH 42/56] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/system/reports_practice_filter_test.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/system/reports_practice_filter_test.rb b/test/system/reports_practice_filter_test.rb index 45e73c8b57f..70c4e3092f8 100644 --- a/test/system/reports_practice_filter_test.rb +++ b/test/system/reports_practice_filter_test.rb @@ -34,9 +34,4 @@ class ReportsPracticeFilterTest < ApplicationSystemTestCase assert_text 'レポート1', wait: 5 assert_no_text 'レポート2', wait: 5 end - - test 'practice filter is hidden when unchecked parameter is present' do - visit reports_unchecked_index_path - assert_no_selector 'select#js-choices-single-select', wait: 5 - end end From cc1493ca969f11b217b8ada8dd3464614d9a3883 Mon Sep 17 00:00:00 2001 From: Masaki Komagata Date: Thu, 2 Oct 2025 14:11:02 +0900 Subject: [PATCH 43/56] =?UTF-8?q?textarea=E3=81=AEsanitize=E3=81=AE?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E3=82=B9=E3=82=AD=E3=83=83?= =?UTF-8?q?=E3=83=97=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit markdown-it-purifierに問題があるために一時的に外している これが下に戻ったときにこのテストも戻す。 --- test/system/markdown_test.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/system/markdown_test.rb b/test/system/markdown_test.rb index 1b220e71ac4..5fea5b0a5ae 100644 --- a/test/system/markdown_test.rb +++ b/test/system/markdown_test.rb @@ -16,6 +16,8 @@ class MarkdownTest < ApplicationSystemTestCase end test 'javascript link is sanitized' do + skip 'markdown-it-purifierの問題が解決したら戻す' + visit_with_auth new_page_path, 'komagata' fill_in 'page[title]', with: 'リンク除去' fill_in 'page[body]', with: 'リンク' From d9e852bb4da80a7069a0476d2780f6d6a09aa6b5 Mon Sep 17 00:00:00 2001 From: Masaki Komagata Date: Thu, 2 Oct 2025 15:25:29 +0900 Subject: [PATCH 44/56] =?UTF-8?q?=E6=9C=AA=E3=83=81=E3=82=A7=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=81=AE=E6=97=A5=E5=A0=B1=E3=82=92=E4=B8=80=E6=8B=AC?= =?UTF-8?q?=E3=81=A7=E9=96=8B=E3=81=8F=E3=83=9C=E3=82=BF=E3=83=B3=E3=82=92?= =?UTF-8?q?=E5=BE=A9=E6=B4=BB=E3=81=95=E3=81=9B=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/reports/index.html.slim | 2 ++ config/routes/reports.rb | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/views/reports/index.html.slim b/app/views/reports/index.html.slim index 7c237d54691..956309b9bc0 100644 --- a/app/views/reports/index.html.slim +++ b/app/views/reports/index.html.slim @@ -44,4 +44,6 @@ main.page-main .card-list.a-card .card-list__items = render partial: 'reports/report', collection: @reports, as: :report, locals: { user_icon_display: true, actions_display: true } + - if mentor_login? && controller_path == 'reports/unchecked' + = render partial: 'unconfirmed_links_open', locals: { label: '未チェックの日報を一括で開く' } = paginate @reports diff --git a/config/routes/reports.rb b/config/routes/reports.rb index 7a72dedf028..e9ad5259b7a 100644 --- a/config/routes/reports.rb +++ b/config/routes/reports.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true Rails.application.routes.draw do - resources :reports do - resources :checks, only: [:create, :destroy] - end namespace :reports do resources :unchecked, only: %i[index] end + resources :reports do + resources :checks, only: [:create, :destroy] + end end From 96f3cd0db70ad3fcd71691f7b5598d8ba789b27f Mon Sep 17 00:00:00 2001 From: machida Date: Thu, 2 Oct 2025 13:34:41 +0900 Subject: [PATCH 45/56] =?UTF-8?q?=E6=96=B0=E6=96=99=E9=87=91=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/helpers/meta_tags_helper.rb | 4 +-- .../stylesheets/lp/blocks/lp/_lp-price.sass | 29 +++++++++++++---- .../stylesheets/lp/layouts/_l-cards.sass | 2 +- app/views/welcome/_pricing.html.slim | 19 +++-------- .../_course_fees.html.slim | 30 +++++------------ .../_course_overview.html.slim | 6 ++-- app/views/welcome/index.html.slim | 2 +- app/views/welcome/law.html.slim | 2 +- app/views/welcome/pricing.html.slim | 14 ++------ app/views/welcome/training.html.slim | 32 +++++++------------ test/system/admin/campaigns_test.rb | 2 +- test/system/articles_test.rb | 2 +- 12 files changed, 61 insertions(+), 83 deletions(-) diff --git a/app/helpers/meta_tags_helper.rb b/app/helpers/meta_tags_helper.rb index 2852fa7ef62..827095e2538 100644 --- a/app/helpers/meta_tags_helper.rb +++ b/app/helpers/meta_tags_helper.rb @@ -7,7 +7,7 @@ def default_meta_tags site: 'FBC', reverse: true, charset: 'utf-8', - description: '月額29,800円、全機能が使えるお試し期間付き。FBCは現場の即戦力になるためのスキルとプログラミングの楽しさを伝える、現役ソフトウェアエンジニアが考える理想のプログラミングスクールの実現に励んでいます。', + description: '月額32,780円(税込)、全機能が使えるお試し期間付き。FBCは現場の即戦力になるためのスキルとプログラミングの楽しさを伝える、現役ソフトウェアエンジニアが考える理想のプログラミングスクールの実現に励んでいます。', viewport: 'width=device-width, initial-scale=1.0', og: { title: :title, @@ -31,7 +31,7 @@ def default_meta_tags def welcome_meta_tags default_meta_tags.deep_merge({ title:, - description: '月額29,800円、全機能が使えるお試し期間付き。FBCは現場の即戦力になるためのスキルとプログラミングの楽しさを伝える、現役ソフトウェアエンジニアが考える理想のプログラミングスクールの実現に励んでいます。', + description: '月額32,780円(税込)、全機能が使えるお試し期間付き。FBCは現場の即戦力になるためのスキルとプログラミングの楽しさを伝える、現役ソフトウェアエンジニアが考える理想のプログラミングスクールの実現に励んでいます。', og: { title: title || 'FJORD BOOT CAMP(フィヨルドブートキャンプ)', description: :description diff --git a/app/javascript/stylesheets/lp/blocks/lp/_lp-price.sass b/app/javascript/stylesheets/lp/blocks/lp/_lp-price.sass index 67840e861cd..60e08c5c225 100644 --- a/app/javascript/stylesheets/lp/blocks/lp/_lp-price.sass +++ b/app/javascript/stylesheets/lp/blocks/lp/_lp-price.sass @@ -9,20 +9,22 @@ font-size: .875rem +media-breakpoint-down(sm) font-size: .5625rem + &.is-total + gap: .25em &.is-sm justify-content: flex-start +media-breakpoint-up(lg) font-size: .5625em .lp-price__tax - font-size: 1rem + font-size: 1.5rem +media-breakpoint-only(md) font-size: .5em .lp-price__tax - font-size: .875rem + font-size: 1rem +media-breakpoint-down(sm) font-size: .375em .lp-price__tax - font-size: .75rem + font-size: .875rem .lp-price__label +text-block(1.25em 1, 700) @@ -40,6 +42,7 @@ display: flex align-self: baseline gap: .5em + flex-wrap: wrap .lp-price__amount +text-block(6.25em 1, 900) @@ -51,14 +54,28 @@ align-self: baseline .lp-price__details - +text-block(1.25em 1, 800) + +text-block(2.25em 1, 800) display: flex align-self: baseline gap: .125em .lp-price__separator font-weight: 100 + align-self: baseline + +.lp-price__per-person + align-self: baseline + +.lp-price__tax + font-size: 1.25em + align-self: baseline + +.lp-price__total-value + display: flex + align-self: baseline + gap: .25em + font-size: 1.5em + font-weight: 600 .lp-price-note - +media-breakpoint-down(sm) - font-size: .75rem + line-height: 1.4 diff --git a/app/javascript/stylesheets/lp/layouts/_l-cards.sass b/app/javascript/stylesheets/lp/layouts/_l-cards.sass index eb45bdd6248..accf9d8b1a2 100644 --- a/app/javascript/stylesheets/lp/layouts/_l-cards.sass +++ b/app/javascript/stylesheets/lp/layouts/_l-cards.sass @@ -35,6 +35,6 @@ .l-cards__item-inner flex: 0 0 40rem - max-width: 100% + max-width: calc(100vw - 2rem) .a-card margin-inline: 0 diff --git a/app/views/welcome/_pricing.html.slim b/app/views/welcome/_pricing.html.slim index 6e54607e379..621f33f5cb4 100644 --- a/app/views/welcome/_pricing.html.slim +++ b/app/views/welcome/_pricing.html.slim @@ -14,25 +14,16 @@ section.lp-content.is-lp-bg-2.is-top-title#pricing | 月額 span.lp-price__value span.lp-price__amount - | 29,800 + | 32,780 span.lp-price__currency | 円 - span.lp-price__details - span.lp-price__tax - | (税込) - .new-price-info.text-center.a-notice-block.is-danger.mt-4 - p.text-base - | 2023年10月1日より、価格改定を行います。 - br - | 価格改定後は月額 税抜29,800円(税込32,780円) - br - = link_to 'https://bootcamp.fjord.jp/articles/177', class: 'a-link is-primary', target: '_blank', rel: 'noopener' do - | 価格改定の詳細はこちら - + span.lp-price__details + span.lp-price__tax + | (税込) p.lp-price-note.text-center.mt-4 = link_to training_path do | 法人でのご利用の場合 - | 、月額 99,800円(税込) + | 、月額 109,780円(税込) .lp-content-stack__item section.lp-content-section diff --git a/app/views/welcome/certified_reskill_courses/rails_developer_course/_course_fees.html.slim b/app/views/welcome/certified_reskill_courses/rails_developer_course/_course_fees.html.slim index 7bc408a934c..42ca2c6582d 100644 --- a/app/views/welcome/certified_reskill_courses/rails_developer_course/_course_fees.html.slim +++ b/app/views/welcome/certified_reskill_courses/rails_developer_course/_course_fees.html.slim @@ -9,17 +9,6 @@ section.lp-content.is-lp-bg-2.is-top-title .lp-content-stack .lp-content-stack__item .l-cards.is-stacked - .l-cards__item.is-wide - .l-cards__item-inner - .new-price-info.text-center.a-notice-block.is-danger - p.text-base - | 2023年10月1日より、価格改定を行います。 - br - | その前のお申し込みをおすすめします! - br - = link_to 'https://bootcamp.fjord.jp/articles/177', class: 'a-link is-primary', target: '_blank', rel: 'noopener' do - | 価格改定の詳細はこちら - .l-cards__item.is-wide .l-cards__item-inner .a-card @@ -31,10 +20,10 @@ section.lp-content.is-lp-bg-2.is-top-title .lp-left-image-section__end header.lp-left-image-section__header h3.lp-card-title - | 受講料 + 教材費 + | 受講料 h4.lp-price.is-sm span.lp-price__value - span.lp-price__amount 746,218 + span.lp-price__amount 786,720 span.lp-price__currency 円 span.lp-price__details span.lp-price__tax (税込) @@ -44,11 +33,8 @@ section.lp-content.is-lp-bg-2.is-top-title | Railsエンジニア(Reスキル認定講座対応)コースの場合、 = link_to practices_path do | 通常のRailsエンジニアコース - | とは違い、受講料(715,200円)と教材費(31,018円)を + | とは違い、受講料(税込 786,720円)を | サブスクではなく、一括でお支払いいただく必要があります。 - p - | Railsエンジニア(Reスキル認定講座対応)コースの場合、 - | フィヨルドブートキャンプで教材を揃え、ご自宅に発送します。 .l-cards__item.is-wide .l-cards__item-inner .a-card.is-danger @@ -62,14 +48,14 @@ section.lp-content.is-lp-bg-2.is-top-title | 給付金最大80% h4.lp-price.is-sm span.lp-price__value - span.lp-price__amount 596,974 + span.lp-price__amount 629,376 span.lp-price__currency 円 .lp-card-description .a-short-text p | 給付金最大80%を受給した場合、 - | 受講料 + 教材費746,218円の80%である - | 596,974円が給付されます。 + | 受講料(税込)の80%である + | 629,376円が給付されます。 .lp-left-image-section .lp-left-image-section__inner .lp-left-image-section__start.is-hidden-sm-down @@ -80,14 +66,14 @@ section.lp-content.is-lp-bg-2.is-top-title | 最大給付金適用後の自己負担額 h4.lp-price.is-sm span.lp-price__value - span.lp-price__amount 149,244 + span.lp-price__amount 157,344 span.lp-price__currency 円 .lp-card-description .a-short-text p | 給付金最大80%を受給した場合、 | 実質自己負担額は - | 149,244円になります。 + | 157,344円になります。 .lp-content-stack__item .lp-content__description .l-inner-container.is-sm diff --git a/app/views/welcome/certified_reskill_courses/rails_developer_course/_course_overview.html.slim b/app/views/welcome/certified_reskill_courses/rails_developer_course/_course_overview.html.slim index 79bb9f6896f..b3b1ae3417e 100644 --- a/app/views/welcome/certified_reskill_courses/rails_developer_course/_course_overview.html.slim +++ b/app/views/welcome/certified_reskill_courses/rails_developer_course/_course_overview.html.slim @@ -73,9 +73,9 @@ section.lp-content.is-lp-bg-1.is-top-title | 受講料 td p - | 715,200円(税込) + | 786,720円(税込) br - | ※授業料に必須教材費は含まれていません。 + | ※受講料に必須教材費は含まれていません。 tr th | 必須教材費 @@ -84,6 +84,8 @@ section.lp-content.is-lp-bg-1.is-top-title | 31,018円(税込) br | ※カリキュラムで指定している必須書籍の合計金額。 + | セールの状況や電子書籍 or 紙の書籍の選択などで + | 金額が変わります。 tr th | 受講料の支払方法 diff --git a/app/views/welcome/index.html.slim b/app/views/welcome/index.html.slim index 4643dfcccee..568ce7945e1 100644 --- a/app/views/welcome/index.html.slim +++ b/app/views/welcome/index.html.slim @@ -1,5 +1,5 @@ - set_meta_tags(site: 'プログラミングスクール FJORD BOOT CAMP(フィヨルドブートキャンプ)', - description: '月額29,800円、全機能が使えるお試し期間付き。FBCは現場の即戦力になるためのスキルとプログラミングの楽しさを伝える、現役ソフトウェアエンジニアが考える理想のプログラミングスクールの実現に励んでいます。') + description: '月額32,780円(税込)、全機能が使えるお試し期間付き。FBCは現場の即戦力になるためのスキルとプログラミングの楽しさを伝える、現役ソフトウェアエンジニアが考える理想のプログラミングスクールの実現に励んでいます。') - content_for :extra_body_classes, 'welcome welcome-home' - content_for :head_last do = javascript_include_tag 'https://sdk.form.run/js/v2/formrun.js' diff --git a/app/views/welcome/law.html.slim b/app/views/welcome/law.html.slim index d18019a0f87..157e1ea0171 100644 --- a/app/views/welcome/law.html.slim +++ b/app/views/welcome/law.html.slim @@ -1,6 +1,6 @@ - title '特定商取引法に基づく表記' - set_meta_tags(site: 'FJORD BOOT CAMP(フィヨルドブートキャンプ)', - description: '「特定商取引に関する法律」第11条(通信販売についての広告)に基づきこのページに明示いたします。オンラインプログラミングスクールのフィヨルドブートキャンプは月額29,800円、全機能が使えるお試し期間付き。') + description: '「特定商取引に関する法律」第11条(通信販売についての広告)に基づきこのページに明示いたします。オンラインプログラミングスクールのフィヨルドブートキャンプは月額32,780円(税込)、全機能が使えるお試し期間付き。') header.lp-page-header .l-container diff --git a/app/views/welcome/pricing.html.slim b/app/views/welcome/pricing.html.slim index 198e702c363..bffbd821d26 100644 --- a/app/views/welcome/pricing.html.slim +++ b/app/views/welcome/pricing.html.slim @@ -3,7 +3,7 @@ ruby: title '料金' trial_period = Campaign.current_trial_period - set_meta_tags(site: 'FJORD BOOT CAMP(フィヨルドブートキャンプ)', - description: 'フィヨルドブートキャンプの利用料は月額29,800円です。クレジットカードでのお支払いになります。初期費用、入会金は一切ありません。') + description: 'フィヨルドブートキャンプの利用料は月額32,780円(税込)です。クレジットカードでのお支払いになります。初期費用、入会金は一切ありません。') article.lp header.lp-content.is-lp-bg-main.is-hero @@ -45,24 +45,16 @@ article.lp | 月額 span.lp-price__value span.lp-price__amount - | 29,800 + | 32,780 span.lp-price__currency | 円 span.lp-price__details span.lp-price__tax | (税込) - .new-price-info.text-center.a-notice-block.is-danger.mt-4 - p.text-base - | 2023年10月1日より、価格改定を行います。 - br - | 価格改定後は月額 税抜29,800円(税込32,780円) - br - = link_to 'https://bootcamp.fjord.jp/articles/177', class: 'a-link is-primary', target: '_blank', rel: 'noopener' do - | 価格改定の詳細はこちら p.lp-price-note.text-center.mt-4 = link_to training_path do | 法人でのご利用の場合 - | 、月額 99,800円(税込) + | 、月額 109,780円(税込) .lp-content__end .lp-content__description.mb-12 .l-inner-container.is-md diff --git a/app/views/welcome/training.html.slim b/app/views/welcome/training.html.slim index fe7cb3d192c..4eca8567328 100644 --- a/app/views/welcome/training.html.slim +++ b/app/views/welcome/training.html.slim @@ -300,7 +300,7 @@ article.lp | 研修の成果も向上します。 section.lp-content.is-lp-bg-1.is-top-title.corporate-training-fee - .l-container.is-md + .l-container.is-lg .lp-content__inner .lp-content__start header.lp-content__header @@ -309,32 +309,22 @@ article.lp .lp-content__end .lp-content-stack .lp-content-stack__item + p.lp-price.mb-2 + span.lp-price__total-value + | 1名につき月額 p.lp-price - span.lp-price__label - | 月額 span.lp-price__value span.lp-price__amount - | 99,800 + | 109,780 span.lp-price__currency | 円 - span.lp-price__details - span.lp-price__tax - | (税込) - span.lp-price__separator - | / - span.lp-price__per-person - | 人 - .new-price-info.text-center.a-notice-block.is-danger.mt-4 - p.text-base - | 2023年10月1日より、価格改定を行います。 - br - | 価格改定後は月額 税抜99,800円(税込109,780円) - br - = link_to 'https://bootcamp.fjord.jp/articles/177', class: 'a-link is-primary', target: '_blank', rel: 'noopener' do - | 価格改定の詳細はこちら - + span.lp-price__details + span.lp-price__tax + | (税込) p.lp-price-note.text-center.mt-4 - | 一般利用の場合は、月額 29,800円(税込) + = link_to pricing_path do + | 一般利用の場合 + | 、月額 32,780円(税込) .lp-content-stack__item h3.lp-content-sub-title.text-center | 一般利用と法人利用の違い diff --git a/test/system/admin/campaigns_test.rb b/test/system/admin/campaigns_test.rb index c2b93dc8282..07c617eb47a 100644 --- a/test/system/admin/campaigns_test.rb +++ b/test/system/admin/campaigns_test.rb @@ -85,7 +85,7 @@ class CampaignsTest < ApplicationSystemTestCase # example_end_at = (TODAY + 3.days).strftime('%-m月%-d日10時10分9秒') # example_pay_at = (TODAY + 3.days).strftime('%-m月%-d日10時10分10秒') - # assert_text "3日間のお試し期間\n月額29,800円は決して安い金額ではありません。" + # assert_text "3日間のお試し期間\n月額32,780円(税込)は決して安い金額ではありません。" # assert_text 'フィヨルドブートキャンプを使うべきかを判断するために3日間のお試し期間を用意' # assert_text 'その3日間、がっつりフィヨルドブートキャンプを見たり使ったりして判断してください。' diff --git a/test/system/articles_test.rb b/test/system/articles_test.rb index e88284c6852..75d5e3063d1 100644 --- a/test/system/articles_test.rb +++ b/test/system/articles_test.rb @@ -265,7 +265,7 @@ class ArticlesTest < ApplicationSystemTestCase end assert_text '記事を作成しました' - meta_description = '月額29,800円、全機能が使えるお試し期間付き。FBCは現場の即戦力になるためのスキルとプログラミングの楽しさを伝える、現役ソフトウェアエンジニアが考える理想のプログラミングスクールの実現に励んでいます。' + meta_description = '月額32,780円(税込)、全機能が使えるお試し期間付き。FBCは現場の即戦力になるためのスキルとプログラミングの楽しさを伝える、現役ソフトウェアエンジニアが考える理想のプログラミングスクールの実現に励んでいます。' assert_selector "meta[name='description'][content='#{meta_description}']", visible: false assert_selector "meta[property='og:description'][content='#{meta_description}']", visible: false assert_selector "meta[name='twitter:description'][content='#{meta_description}']", visible: false From dcb4bf715fa6702a6b2c984d068d4b3d4a2dc92e Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Sun, 28 Sep 2025 16:55:22 +0900 Subject: [PATCH 46/56] =?UTF-8?q?not=5Fsolved=5Fquestion=5Fcount=E3=83=A1?= =?UTF-8?q?=E3=82=BD=E3=83=83=E3=83=89=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/cache.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/cache.rb b/app/models/cache.rb index 020f1a9df80..2001a10079e 100644 --- a/app/models/cache.rb +++ b/app/models/cache.rb @@ -54,7 +54,7 @@ def delete_self_assigned_no_replied_product_count(user_id) def not_solved_question_count Rails.cache.fetch 'not_solved_question_count' do - Question.not_solved.count + Question.not_solved.not_wip.count end end From fb0e6a1886c1f30521f6a6bb1dba38f6eb174d65 Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Sun, 28 Sep 2025 18:01:12 +0900 Subject: [PATCH 47/56] =?UTF-8?q?unsolved=5Fbadge=E3=83=A1=E3=82=BD?= =?UTF-8?q?=E3=83=83=E3=83=89=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/question.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/question.rb b/app/models/question.rb index c3cbd2d5a70..27a82e1277c 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -82,7 +82,7 @@ def unsolved_badge(current_user:, practice_id: nil) if practice_id.present? Question.not_solved.not_wip.where(practice_id:).size else - Question.not_solved.not_wip.size + ::Cache.not_solved_question_count end end end From ff7f6b83fbba39e96fc5a9e2be3ad21b7e9ae6a0 Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Mon, 29 Sep 2025 13:48:14 +0900 Subject: [PATCH 48/56] =?UTF-8?q?=E3=82=B0=E3=83=AD=E3=83=BC=E3=83=90?= =?UTF-8?q?=E3=83=AB=E3=83=8A=E3=83=93=E3=82=B2=E3=83=BC=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=81=AEQ&A=E3=81=AB=E8=A1=A8=E7=A4=BA=E3=81=99?= =?UTF-8?q?=E3=82=8B=E6=9C=AA=E8=A7=A3=E6=B1=BA=E8=B3=AA=E5=95=8F=E6=95=B0?= =?UTF-8?q?=E3=81=AE=E5=8F=82=E7=85=A7=E5=85=88=E3=82=92Cache=E3=81=AB?= =?UTF-8?q?=E7=BD=AE=E6=8F=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/application/_global_nav.slim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/application/_global_nav.slim b/app/views/application/_global_nav.slim index 2fc3daf3988..c3ad4c750ed 100644 --- a/app/views/application/_global_nav.slim +++ b/app/views/application/_global_nav.slim @@ -35,9 +35,9 @@ nav.global-nav = link_to questions_path(target: 'not_solved'), class: "global-nav-links__link #{current_link(/^questions/)}" do .global-nav-links__link-icon i.fa-solid.fa-comments-question-check - - if Question.not_solved.not_wip.count.positive? + - if Cache.not_solved_question_count.positive? .global-nav__item-count.a-notification-count - = Question.not_solved.not_wip.count + = Cache.not_solved_question_count .global-nav-links__link-label Q&A li.global-nav-links__item = link_to '/pages', class: "global-nav-links__link #{(@page&.slug != 'help' && @page&.slug != 'help-adviser') && current_link(/^pages/)}" do From 2c6617f3ea02c5013a26d467a31079d5866668b8 Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Tue, 30 Sep 2025 18:42:02 +0900 Subject: [PATCH 49/56] =?UTF-8?q?=E3=83=87=E3=83=90=E3=83=83=E3=82=B0?= =?UTF-8?q?=E7=94=A8=E3=81=ABRails.logger=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/cache.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/cache.rb b/app/models/cache.rb index 2001a10079e..1f3b96702e1 100644 --- a/app/models/cache.rb +++ b/app/models/cache.rb @@ -54,6 +54,7 @@ def delete_self_assigned_no_replied_product_count(user_id) def not_solved_question_count Rails.cache.fetch 'not_solved_question_count' do + Rails.logger.info '[CACHE MISS] Executing DB query for not_solved_question_count' Question.not_solved.not_wip.count end end From 528fcef6f22b527cdfd7411f7fc744035e89904d Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Thu, 2 Oct 2025 09:14:40 +0900 Subject: [PATCH 50/56] =?UTF-8?q?=E5=9B=9E=E7=AD=94=E3=81=AE=E4=BD=9C?= =?UTF-8?q?=E6=88=90=E3=83=BB=E6=9B=B4=E6=96=B0=E6=99=82=E3=81=AE=E4=B8=8D?= =?UTF-8?q?=E8=A6=81=E3=81=AA=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5?= =?UTF-8?q?=E3=82=AF=E3=83=AA=E3=82=A2=E3=82=92=E9=99=A4=E5=8E=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/answers_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/api/answers_controller.rb b/app/controllers/api/answers_controller.rb index e61262a8b9b..e2c25ee4240 100644 --- a/app/controllers/api/answers_controller.rb +++ b/app/controllers/api/answers_controller.rb @@ -30,7 +30,6 @@ def create @answer.user = current_user if @answer.save ActiveSupport::Notifications.instrument('answer.create', answer: @answer) - Newspaper.publish(:answer_save, { answer: @answer }) render partial: 'questions/answer', locals: { question:, answer: @answer, user: current_user }, status: :created else head :bad_request @@ -39,7 +38,6 @@ def create def update if @answer.update(answer_params) - Newspaper.publish(:answer_save, { answer: @answer }) head :ok else head :bad_request From a470dcb588a32e94c9bb3f4d4069d2c96bafa983 Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Thu, 2 Oct 2025 13:18:54 +0900 Subject: [PATCH 51/56] =?UTF-8?q?=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7?= =?UTF-8?q?=E3=83=A5=E3=82=AF=E3=83=AA=E3=82=A2=E3=81=AE=E3=83=87=E3=83=90?= =?UTF-8?q?=E3=83=83=E3=82=B0=E3=81=AE=E3=81=9F=E3=82=81=E3=80=81Rails.log?= =?UTF-8?q?ger=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/answer_cache_destroyer.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/answer_cache_destroyer.rb b/app/models/answer_cache_destroyer.rb index c374dc9650d..b39e1be3025 100644 --- a/app/models/answer_cache_destroyer.rb +++ b/app/models/answer_cache_destroyer.rb @@ -4,5 +4,6 @@ class AnswerCacheDestroyer def call(payload) _answer = payload[:answer] Cache.delete_not_solved_question_count + Rails.logger.info '[AnswerCacheDestroyer] Cache destroyed for unsolved question count.' end end From 2b8ccfa7f74d09e5b26fa1918ff7620e82587522 Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Thu, 2 Oct 2025 13:20:55 +0900 Subject: [PATCH 52/56] =?UTF-8?q?=E5=89=8A=E9=99=A4=E3=81=99=E3=82=8B?= =?UTF-8?q?=E5=9B=9E=E7=AD=94=E3=81=8C=E3=83=99=E3=82=B9=E3=83=88=E3=82=A2?= =?UTF-8?q?=E3=83=B3=E3=82=B5=E3=83=BC=E3=81=AE=E5=A0=B4=E5=90=88=E3=81=AB?= =?UTF-8?q?=E3=81=AE=E3=81=BF=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5?= =?UTF-8?q?=E3=82=AF=E3=83=AA=E3=82=A2=E3=82=92=E5=AE=9F=E8=A1=8C=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/answers_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/answers_controller.rb b/app/controllers/api/answers_controller.rb index e2c25ee4240..a9353d1813f 100644 --- a/app/controllers/api/answers_controller.rb +++ b/app/controllers/api/answers_controller.rb @@ -45,8 +45,8 @@ def update end def destroy + Newspaper.publish(:answer_destroy, { answer: @answer }) if @answer.is_a?(CorrectAnswer) @answer.destroy - Newspaper.publish(:answer_destroy, { answer: @answer }) end private From c7420e4bc9e871dfae8899ec0178cf7b7215567a Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Thu, 2 Oct 2025 13:23:10 +0900 Subject: [PATCH 53/56] =?UTF-8?q?=E5=9B=9E=E7=AD=94=E5=89=8A=E9=99=A4?= =?UTF-8?q?=E3=81=AE=E3=82=A4=E3=83=99=E3=83=B3=E3=83=88=E3=83=AA=E3=82=B9?= =?UTF-8?q?=E3=83=8A=E3=83=BC=E3=81=AB=E3=81=8A=E3=81=84=E3=81=A6=E3=80=81?= =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=ABcancelBestAnswer=E3=83=A1=E3=82=BD?= =?UTF-8?q?=E3=83=83=E3=83=89=E3=82=92=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=9F=E9=83=A8=E5=88=86=E3=82=92=E5=89=8A?= =?UTF-8?q?=E9=99=A4=E3=81=97=E3=80=81=E5=9B=9E=E7=AD=94=E5=89=8A=E9=99=A4?= =?UTF-8?q?=E6=99=82=E3=81=AB2=E9=87=8D=E3=81=AB=E3=82=AD=E3=83=A3?= =?UTF-8?q?=E3=83=83=E3=82=B7=E3=83=A5=E3=82=AF=E3=83=AA=E3=82=A2=E3=81=8C?= =?UTF-8?q?=E5=AE=9F=E8=A1=8C=E3=81=95=E3=82=8C=E3=82=8B=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E8=A7=A3=E6=B1=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/javascript/initializeAnswer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/javascript/initializeAnswer.js b/app/javascript/initializeAnswer.js index 1fd15e76fc8..eff9d9908a2 100644 --- a/app/javascript/initializeAnswer.js +++ b/app/javascript/initializeAnswer.js @@ -115,7 +115,6 @@ export default function initializeAnswer(answer) { if (window.confirm('本当に宜しいですか?')) { deleteAnswer(answerId) if (answerBadgeElement.classList.contains('correct-answer')) { - cancelBestAnswer(answerId, questionId) const otherCancelBestAnswerButtons = document.querySelectorAll( '.make-best-answer-button' ) From 14e1244dfef040f4978bbcc963ec457531c26c11 Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Thu, 2 Oct 2025 17:51:29 +0900 Subject: [PATCH 54/56] =?UTF-8?q?Rails.logger=E3=81=ABAnswerCacheControlle?= =?UTF-8?q?r=E3=81=AE=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97=E5=85=83?= =?UTF-8?q?=E6=83=85=E5=A0=B1=E3=82=92=E5=87=BA=E5=8A=9B=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/answers_controller.rb | 7 ++++++- app/controllers/api/correct_answers_controller.rb | 10 ++++++++-- app/models/answer_cache_destroyer.rb | 3 ++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/answers_controller.rb b/app/controllers/api/answers_controller.rb index a9353d1813f..284c9e7dbfd 100644 --- a/app/controllers/api/answers_controller.rb +++ b/app/controllers/api/answers_controller.rb @@ -45,7 +45,12 @@ def update end def destroy - Newspaper.publish(:answer_destroy, { answer: @answer }) if @answer.is_a?(CorrectAnswer) + if @answer.is_a?(CorrectAnswer) + Newspaper.publish(:answer_destroy, { + answer: @answer, + action: "#{self.class.name}##{action_name}" + }) + end @answer.destroy end diff --git a/app/controllers/api/correct_answers_controller.rb b/app/controllers/api/correct_answers_controller.rb index 1b356279b83..bac9caebf3f 100644 --- a/app/controllers/api/correct_answers_controller.rb +++ b/app/controllers/api/correct_answers_controller.rb @@ -7,7 +7,10 @@ def create @answer = @question.answers.find(params[:answer_id]) @answer.type = 'CorrectAnswer' if @answer.save - Newspaper.publish(:answer_save, { answer: @answer }) + Newspaper.publish(:answer_save, { + answer: @answer, + action: "#{self.class.name}##{action_name}" + }) ActiveSupport::Notifications.instrument('correct_answer.save', answer: @answer) head :ok else @@ -18,7 +21,10 @@ def create def update answer = @question.answers.find(params[:answer_id]) answer.update!(type: '') - Newspaper.publish(:answer_save, { answer: @answer }) + Newspaper.publish(:answer_save, { + answer: @answer, + action: "#{self.class.name}##{action_name}" + }) end private diff --git a/app/models/answer_cache_destroyer.rb b/app/models/answer_cache_destroyer.rb index b39e1be3025..b5ede21f2a0 100644 --- a/app/models/answer_cache_destroyer.rb +++ b/app/models/answer_cache_destroyer.rb @@ -3,7 +3,8 @@ class AnswerCacheDestroyer def call(payload) _answer = payload[:answer] + action = payload[:action] Cache.delete_not_solved_question_count - Rails.logger.info '[AnswerCacheDestroyer] Cache destroyed for unsolved question count.' + Rails.logger.info "[AnswerCacheDestroyer] #{action} Cache destroyed for unsolved question count." end end From 742f57171c8485a671717d621a679aa1116031ca Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Thu, 2 Oct 2025 17:53:59 +0900 Subject: [PATCH 55/56] =?UTF-8?q?=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97?= =?UTF-8?q?=E6=83=85=E5=A0=B1=E3=82=92Rails.logger=E3=81=AB=E6=B8=A1?= =?UTF-8?q?=E3=81=99=E3=81=9F=E3=82=81=E3=81=AEpayload=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/models/question_auto_closer.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/question_auto_closer.rb b/app/models/question_auto_closer.rb index 19792cf7568..dc74195bf66 100644 --- a/app/models/question_auto_closer.rb +++ b/app/models/question_auto_closer.rb @@ -98,7 +98,11 @@ def select_as_best_answer(close_answer) end def publish_events(correct_answer) - Newspaper.publish(:answer_save, { answer: correct_answer }) + method_name = __method__ + Newspaper.publish(:answer_save, { + answer: correct_answer, + action: "#{name}.#{method_name}" + }) ActiveSupport::Notifications.instrument('correct_answer.save', answer: correct_answer) end end From d388980ad6473d2c5ffb7df6d87730af9004c63e Mon Sep 17 00:00:00 2001 From: Miya096jp Date: Thu, 2 Oct 2025 18:30:16 +0900 Subject: [PATCH 56/56] =?UTF-8?q?update=E3=81=A7=E5=AE=9A=E7=BE=A9?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=82=8B=E3=83=AD=E3=83=BC=E3=82=AB=E3=83=AB?= =?UTF-8?q?=E5=A4=89=E6=95=B0answer=E3=82=92Newspaper=E3=81=AEpayload?= =?UTF-8?q?=E3=81=AB=E6=B8=A1=E3=81=99=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/api/correct_answers_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/correct_answers_controller.rb b/app/controllers/api/correct_answers_controller.rb index bac9caebf3f..41a29413c02 100644 --- a/app/controllers/api/correct_answers_controller.rb +++ b/app/controllers/api/correct_answers_controller.rb @@ -22,7 +22,7 @@ def update answer = @question.answers.find(params[:answer_id]) answer.update!(type: '') Newspaper.publish(:answer_save, { - answer: @answer, + answer:, action: "#{self.class.name}##{action_name}" }) end