From fa7e9094e2e20e463fc58c4138bf8e46e00fc093 Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Sat, 1 Nov 2025 15:36:50 +0900 Subject: [PATCH 1/5] Cosmetic change: delete needless spaces --- lib/tasks/fetch_news.rake | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/tasks/fetch_news.rake b/lib/tasks/fetch_news.rake index 8e6b444c6..17cbf6371 100644 --- a/lib/tasks/fetch_news.rake +++ b/lib/tasks/fetch_news.rake @@ -73,7 +73,7 @@ namespace :news do # 新しいアイテムと既存アイテムを分離 truly_new_items = [] updated_items = [] - + new_items.each do |new_item| if existing_items_hash.key?(new_item['url']) existing_item = existing_items_hash[new_item['url']] @@ -90,10 +90,10 @@ namespace :news do max_existing_id = existing_news.map { |item| item['id'].to_i }.max || 0 # 新しいアイテムのみに ID を割り当て(古い順) - truly_new_items_sorted = truly_new_items.sort_by { |item| - Time.parse(item['published_at']) + truly_new_items_sorted = truly_new_items.sort_by { |item| + Time.parse(item['published_at']) } - + truly_new_items_sorted.each_with_index do |item, index| item['id'] = max_existing_id + index + 1 end @@ -106,8 +106,8 @@ namespace :news do all_items = unchanged_items + updated_items + truly_new_items_sorted # 日付降順ソート - sorted_items = all_items.sort_by { |item| - Time.parse(item['published_at']) + sorted_items = all_items.sort_by { |item| + Time.parse(item['published_at']) }.reverse File.open('db/news.yml', 'w') do |f| From f85b8dc556d03cb805cd03760bf342957c3e02b3 Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Sat, 1 Nov 2025 15:52:20 +0900 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=20news=20=E3=82=BF=E3=82=B9?= =?UTF-8?q?=E3=82=AF=E3=82=92=E7=B5=B1=E5=90=88=E3=81=97=E3=81=A6=E4=B8=80?= =?UTF-8?q?=E8=B2=AB=E6=80=A7=E3=82=92=E5=90=91=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #1757 の一部として、分離されていた news:fetch と news:import_from_yaml を 単一の news:upsert タスクに統合。他の rake タスクとの設計一貫性を保つ。 変更内容: - lib/tasks/fetch_news.rake と lib/tasks/import_news.rake を削除 - lib/tasks/news.rake を新規作成(統合版) - RSS フィードからデータベースまでを一貫処理 - 後方互換性のためエイリアスタスクを提供 他のタスクとの一貫性: - podcasts:upsert (RSS → DB 直接) - dojo_event_services:upsert (YAML → DB 直接) - 同様の統合パターンを採用 --- lib/tasks/import_news.rake | 42 ------------------ lib/tasks/{fetch_news.rake => news.rake} | 54 +++++++++++++++++++++--- 2 files changed, 49 insertions(+), 47 deletions(-) delete mode 100644 lib/tasks/import_news.rake rename lib/tasks/{fetch_news.rake => news.rake} (70%) diff --git a/lib/tasks/import_news.rake b/lib/tasks/import_news.rake deleted file mode 100644 index 45c77ee05..000000000 --- a/lib/tasks/import_news.rake +++ /dev/null @@ -1,42 +0,0 @@ -require 'yaml' - -namespace :news do - desc 'db/news.yml を読み込んで News テーブルを upsert する' - task import_from_yaml: :environment do - file_logger = ActiveSupport::Logger.new('log/news.log') - console = ActiveSupport::Logger.new(STDOUT) - logger = ActiveSupport::BroadcastLogger.new(file_logger, console) - - logger.info "==== START news:import_from_yaml ====" - - yaml_path = Rails.root.join('db', 'news.yml') - raw = YAML.safe_load(File.read(yaml_path), permitted_classes: [Time], aliases: true) - - # entries を計算 - entries = raw['news'] || [] - new_count = 0 - updated_count = 0 - - entries.each do |attrs| - news = News.find_or_initialize_by(url: attrs['url']) - is_new = news.new_record? - - news.assign_attributes( - title: attrs['title'], - published_at: attrs['published_at'] - ) - - if is_new || news.changed? - news.save! - status = is_new ? 'new' : 'updated' - new_count += 1 if is_new - updated_count += 1 unless is_new - - logger.info "[News] #{news.published_at.to_date} #{news.title} (#{status})" - end - end - - logger.info "Imported #{new_count + updated_count} items (#{new_count} new, #{updated_count} updated)." - logger.info "==== END news:import_from_yaml ====" - end -end diff --git a/lib/tasks/fetch_news.rake b/lib/tasks/news.rake similarity index 70% rename from lib/tasks/fetch_news.rake rename to lib/tasks/news.rake index 17cbf6371..6ace99a6d 100644 --- a/lib/tasks/fetch_news.rake +++ b/lib/tasks/news.rake @@ -37,14 +37,14 @@ def item_to_hash(item) end namespace :news do - desc 'RSS フィードから最新ニュースを取得し、db/news.yml に書き出す' - task fetch: :environment do + desc 'RSS フィードから最新ニュースを取得してデータベースに upsert' + task upsert: :environment do # ロガー設定(ファイル+コンソール出力) file_logger = ActiveSupport::Logger.new('log/news.log') console = ActiveSupport::Logger.new(STDOUT) logger = ActiveSupport::BroadcastLogger.new(file_logger, console) - logger.info('==== START news:fetch ====') + logger.info('==== START news:upsert ====') # 既存の news.yml を読み込み yaml_path = Rails.root.join('db', 'news.yml') @@ -110,6 +110,7 @@ namespace :news do Time.parse(item['published_at']) }.reverse + # YAML ファイルに書き出し File.open('db/news.yml', 'w') do |f| formatted_items = sorted_items.map do |item| { @@ -124,6 +125,49 @@ namespace :news do end logger.info("✅ Wrote #{sorted_items.size} items to db/news.yml (#{truly_new_items_sorted.size} new, #{updated_items.size} updated)") - logger.info('==== END news:fetch ====') + + # データベースへの upsert 処理(統合部分) + entries = sorted_items + new_count = 0 + updated_count = 0 + + News.transaction do + entries.each do |attrs| + news = News.find_or_initialize_by(url: attrs['url']) + is_new = news.new_record? + + news.assign_attributes( + title: attrs['title'], + published_at: attrs['published_at'] + ) + + if is_new || news.changed? + news.save! + status = is_new ? 'new' : 'updated' + new_count += 1 if is_new + updated_count += 1 unless is_new + + logger.info "[News] #{news.published_at.to_date} #{news.title} (#{status})" + end + end + end + + logger.info "Imported #{new_count + updated_count} items to database (#{new_count} new, #{updated_count} updated)." + logger.info('==== END news:upsert ====') end -end + + # 後方互換性のためのエイリアス(既存のデプロイ設定などで使われている可能性) + desc '※ Deprecated: news:upsert を使用してください' + task fetch: :environment do + logger = ActiveSupport::Logger.new(STDOUT) + logger.warn "⚠️ news:fetch は非推奨です。news:upsert を使用してください" + Rake::Task['news:upsert'].invoke + end + + desc '※ Deprecated: news:upsert を使用してください' + task import_from_yaml: :environment do + logger = ActiveSupport::Logger.new(STDOUT) + logger.warn "⚠️ news:import_from_yaml は非推奨です。news:upsert を使用してください" + Rake::Task['news:upsert'].invoke + end +end \ No newline at end of file From 4cc74c0153277eda7ff1ae1fe95aafece9875493 Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Sat, 1 Nov 2025 15:54:04 +0900 Subject: [PATCH 3/5] =?UTF-8?q?simplify:=20=E5=BE=8C=E6=96=B9=E4=BA=92?= =?UTF-8?q?=E6=8F=9B=E6=80=A7=E3=82=A8=E3=82=A4=E3=83=AA=E3=82=A2=E3=82=B9?= =?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 RSS取得・インポートタスクなので、後方互換性は不要。 よりシンプルな実装に変更。 - news:fetch エイリアスを削除 - news:import_from_yaml エイリアスを削除 - news:upsert のみ提供 --- lib/tasks/news.rake | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/tasks/news.rake b/lib/tasks/news.rake index 6ace99a6d..a26a4c178 100644 --- a/lib/tasks/news.rake +++ b/lib/tasks/news.rake @@ -156,18 +156,4 @@ namespace :news do logger.info('==== END news:upsert ====') end - # 後方互換性のためのエイリアス(既存のデプロイ設定などで使われている可能性) - desc '※ Deprecated: news:upsert を使用してください' - task fetch: :environment do - logger = ActiveSupport::Logger.new(STDOUT) - logger.warn "⚠️ news:fetch は非推奨です。news:upsert を使用してください" - Rake::Task['news:upsert'].invoke - end - - desc '※ Deprecated: news:upsert を使用してください' - task import_from_yaml: :environment do - logger = ActiveSupport::Logger.new(STDOUT) - logger.warn "⚠️ news:import_from_yaml は非推奨です。news:upsert を使用してください" - Rake::Task['news:upsert'].invoke - end end \ No newline at end of file From 0aea32fd247c7ffee9bb1777d53e566299e41995 Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Sat, 1 Nov 2025 15:58:56 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20news=20=E3=82=BF=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=81=AE=E5=BD=B9=E5=89=B2=E3=82=92=E6=98=8E=E7=A2=BA=E3=81=AB?= =?UTF-8?q?=E5=88=86=E9=9B=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - news:fetch: RSS → YAML(フィード取得) - news:upsert: YAML → DB(データベース投入) dojos タスクと同様の明確な役割分離を実現: - dojos:update_db_by_yaml (YAML → DB) - dojos:migrate_adding_id_to_yaml (DB → YAML) upsert の命名規則に従い、YAML からの DB 投入を upsert とする。 --- lib/tasks/news.rake | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/tasks/news.rake b/lib/tasks/news.rake index a26a4c178..12f9a399d 100644 --- a/lib/tasks/news.rake +++ b/lib/tasks/news.rake @@ -37,14 +37,14 @@ def item_to_hash(item) end namespace :news do - desc 'RSS フィードから最新ニュースを取得してデータベースに upsert' - task upsert: :environment do + desc 'RSS フィードを取得し、db/news.yml に保存' + task fetch: :environment do # ロガー設定(ファイル+コンソール出力) file_logger = ActiveSupport::Logger.new('log/news.log') console = ActiveSupport::Logger.new(STDOUT) logger = ActiveSupport::BroadcastLogger.new(file_logger, console) - logger.info('==== START news:upsert ====') + logger.info('==== START news:fetch ====') # 既存の news.yml を読み込み yaml_path = Rails.root.join('db', 'news.yml') @@ -125,9 +125,21 @@ namespace :news do end logger.info("✅ Wrote #{sorted_items.size} items to db/news.yml (#{truly_new_items_sorted.size} new, #{updated_items.size} updated)") + logger.info('==== END news:fetch ====') + end - # データベースへの upsert 処理(統合部分) - entries = sorted_items + desc 'db/news.yml からデータベースに upsert' + task upsert: :environment do + file_logger = ActiveSupport::Logger.new('log/news.log') + console = ActiveSupport::Logger.new(STDOUT) + logger = ActiveSupport::BroadcastLogger.new(file_logger, console) + + logger.info "==== START news:upsert ====" + + yaml_path = Rails.root.join('db', 'news.yml') + raw = YAML.safe_load(File.read(yaml_path), permitted_classes: [Time], aliases: true) + + entries = raw['news'] || [] new_count = 0 updated_count = 0 @@ -152,8 +164,8 @@ namespace :news do end end - logger.info "Imported #{new_count + updated_count} items to database (#{new_count} new, #{updated_count} updated)." - logger.info('==== END news:upsert ====') + logger.info "Upserted #{new_count + updated_count} items (#{new_count} new, #{updated_count} updated)." + logger.info "==== END news:upsert ====" end -end \ No newline at end of file +end From 2531e7e20b34e08887562fe4d1c86e8fc7174cd9 Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Sat, 1 Nov 2025 16:18:58 +0900 Subject: [PATCH 5/5] =?UTF-8?q?update:=20news:import=5Ffrom=5Fyaml=20?= =?UTF-8?q?=E3=82=92=20news:upsert=20=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit script/release.sh でタスク名を更新し、統合された news.rake の 正しいタスク名を使用する。 --- script/release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/release.sh b/script/release.sh index 9c303d2d7..5046007a8 100755 --- a/script/release.sh +++ b/script/release.sh @@ -3,6 +3,6 @@ set -e bundle exec rails db:migrate bundle exec rails db:seed bundle exec rails dojos:update_db_by_yaml -bundle exec rails news:import_from_yaml +bundle exec rails news:upsert bundle exec rails dojo_event_services:upsert bundle exec rails podcasts:upsert