Skip to content

Commit 43e0f56

Browse files
committed
refactor: YAMLファイル構造をフラット化し処理ロジックを最適化
1 parent 4647c2b commit 43e0f56

File tree

1 file changed

+31
-34
lines changed

1 file changed

+31
-34
lines changed

lib/tasks/news.rake

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ namespace :news do
1010

1111
logger.info('==== START news:fetch ====')
1212

13-
# 本番環境では実サイトのフィード、それ以外(テスト環境など)ではテスト用フェード
13+
# 本番/開発環境では実サイトのフィード、それ以外(テスト環境など)ではテスト用フィード
1414
DOJO_NEWS_FEED = 'https://news.coderdojo.jp/feed/'
1515
TEST_NEWS_FEED = Rails.root.join('spec', 'fixtures', 'sample_news.rss')
16-
RSS_FEED_LIST = Rails.env.production? ?
17-
[DOJO_NEWS_FEED] :
18-
[TEST_NEWS_FEED]
16+
RSS_FEED_LIST = (Rails.env.test? || Rails.env.staging?) ?
17+
[TEST_NEWS_FEED] :
18+
[DOJO_NEWS_FEED]
1919

20-
news_items = RSS_FEED_LIST.flat_map do |feed|
20+
fetched_items = RSS_FEED_LIST.flat_map do |feed|
2121
feed = RSS::Parser.parse(feed, false)
2222
feed.items.map { |item|
2323
{
@@ -28,44 +28,41 @@ namespace :news do
2828
}
2929
end
3030

31-
# 既存データ (YAML) を読み込み、ハッシュに変換
32-
news_yaml_file = File.read Rails.root.join('db', 'news.yml')
33-
existing_news = YAML.safe_load(news_yaml_file).index_by { |item| item['url'] }
31+
# 取得済みニュース (YAML) を読み込み、URL をキーとしたハッシュに変換
32+
news_yaml_file = File.read Rails.root.join('db', 'news.yml')
33+
existing_items = YAML.safe_load(news_yaml_file).index_by { it['url'] }
34+
existing_max_id = existing_items.flat_map { |url, item| item['id'].to_i }.max || 0
3435

35-
# 新しいアイテムと既存アイテムを分離
36-
truly_new_items = []
36+
# 新規記事と既存記事を分離
37+
created_items = []
3738
updated_items = []
3839

39-
news_items.each do |new_item|
40-
if existing_news.key?(new_item['url'])
41-
existing_item = existing_news[new_item['url']]
42-
# タイトルまたは公開日が変わった場合のみ更新
43-
if existing_item['title'] != new_item['title'] || existing_item['published_at'] != new_item['published_at']
44-
updated_items << existing_item.merge(new_item)
40+
fetched_items.each do |fetched_item|
41+
existing_item = existing_items[fetched_item['url']]
42+
43+
if existing_item
44+
# タイトルまたは公開日が変わっていたら更新
45+
if existing_item['title'] != fetched_item['title'] || existing_item['published_at'] != fetched_item['published_at']
46+
updated_items << existing_item.merge(fetched_item)
4547
end
4648
else
47-
truly_new_items << new_item
49+
# 新規アイテムならそのまま追加
50+
created_items << fetched_item
4851
end
4952
end
5053

51-
# 既存の最大IDを取得
52-
max_existing_id = existing_news.map { |item| item['id'].to_i }.max || 0
53-
5454
# 新しいアイテムのみに ID を割り当て(古い順)
55-
truly_new_items_sorted = truly_new_items.sort_by { |item|
56-
Time.parse(item['published_at'])
57-
}
58-
59-
truly_new_items_sorted.each_with_index do |item, index|
60-
item['id'] = max_existing_id + index + 1
55+
created_items.sort_by! { Time.parse it['published_at'] }
56+
created_items.each_with_index do |item, index|
57+
item['id'] = existing_max_id + index + 1
6158
end
6259

6360
# 更新されなかった既存アイテムを取得
64-
updated_urls = updated_items.map { |item| item['url'] }
65-
unchanged_items = existing_news.reject { |item| updated_urls.include?(item['url']) }
61+
updated_urls = updated_items.map { it['url'] }
62+
unchanged_items = existing_items.values.reject { updated_urls.include?(it['url']) }
6663

6764
# 全アイテムをマージ
68-
all_items = unchanged_items + updated_items + truly_new_items_sorted
65+
all_items = unchanged_items + updated_items + created_items
6966

7067
# 日付降順ソート
7168
sorted_items = all_items.sort_by { |item|
@@ -83,18 +80,18 @@ namespace :news do
8380
}
8481
end
8582

86-
f.write({ 'news' => formatted_items }.to_yaml)
83+
f.write(formatted_items.to_yaml)
8784
end
8885

89-
logger.info("✅ Wrote #{sorted_items.size} items to db/news.yml (#{truly_new_items_sorted.size} new, #{updated_items.size} updated)")
86+
logger.info("✅ Wrote #{sorted_items.size} items to db/news.yml (#{created_items.size} new, #{updated_items.size} updated)")
9087
logger.info('==== END news:fetch ====')
9188
end
9289

9390
desc 'db/news.yml からデータベースに upsert'
9491
task upsert: :environment do
95-
file_logger = ActiveSupport::Logger.new('log/news.log')
9692
console = ActiveSupport::Logger.new(STDOUT)
97-
logger = ActiveSupport::BroadcastLogger.new(file_logger, console)
93+
logger_file = ActiveSupport::Logger.new('log/news.log')
94+
logger = ActiveSupport::BroadcastLogger.new(logger_file, console)
9895

9996
logger.info "==== START news:upsert ===="
10097

@@ -112,7 +109,7 @@ namespace :news do
112109
title: attrs['title'],
113110
published_at: attrs['published_at']
114111
)
115-
112+
116113
if is_new || news.changed?
117114
news.save!
118115
status = is_new ? 'new' : 'updated'

0 commit comments

Comments
 (0)