diff --git a/lib/tasks/fetch_news.rake b/lib/tasks/fetch_news.rake index 415d5df25..8e6b444c6 100644 --- a/lib/tasks/fetch_news.rake +++ b/lib/tasks/fetch_news.rake @@ -16,6 +16,26 @@ def safe_open(url) end end +def fetch_rss_items(url, logger) + logger.info("Fetching RSS → #{url}") + begin + rss = safe_open(url) + feed = RSS::Parser.parse(rss, false) + feed.items.map { |item| item_to_hash(item) } + rescue => e + logger.warn("⚠️ Failed to fetch #{url}: #{e.message}") + [] + end +end + +def item_to_hash(item) + { + 'url' => item.link, + 'title' => item.title, + 'published_at' => item.pubDate.to_s + } +end + namespace :news do desc 'RSS フィードから最新ニュースを取得し、db/news.yml に書き出す' task fetch: :environment do @@ -45,24 +65,7 @@ namespace :news do ] end - # RSS 取得&パース - new_items = feed_urls.flat_map do |url| - logger.info("Fetching RSS → #{url}") - begin - rss = safe_open(url) - feed = RSS::Parser.parse(rss, false) - feed.items.map do |item| - { - 'url' => item.link, - 'title' => item.title, - 'published_at' => item.pubDate.to_s - } - end - rescue => e - logger.warn("⚠️ Failed to fetch #{url}: #{e.message}") - [] - end - end + new_items = feed_urls.flat_map { |url| fetch_rss_items(url, logger) } # 既存データをハッシュに変換(URL をキーに) existing_items_hash = existing_news.index_by { |item| item['url'] } @@ -73,12 +76,12 @@ namespace :news do new_items.each do |new_item| if existing_items_hash.key?(new_item['url']) - # 既存アイテムの更新 existing_item = existing_items_hash[new_item['url']] - updated_item = existing_item.merge(new_item) # 新しい情報で更新 - updated_items << updated_item + # タイトルまたは公開日が変わった場合のみ更新 + if existing_item['title'] != new_item['title'] || existing_item['published_at'] != new_item['published_at'] + updated_items << existing_item.merge(new_item) + end else - # 完全に新しいアイテム truly_new_items << new_item end end diff --git a/lib/tasks/import_news.rake b/lib/tasks/import_news.rake index bebe76611..45c77ee05 100644 --- a/lib/tasks/import_news.rake +++ b/lib/tasks/import_news.rake @@ -3,22 +3,40 @@ 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'] ) - news.save! - puts "[news] #{news.published_at.to_date} #{news.title}" + + 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 - puts "Imported #{entries.size} items." + logger.info "Imported #{new_count + updated_count} items (#{new_count} new, #{updated_count} updated)." + logger.info "==== END news:import_from_yaml ====" end end