Skip to content

Commit caae802

Browse files
committed
refactor: YAGNI 原則に従いメソッドをインライン化、Fail-Fast 実装
- 不要なヘルパーメソッド fetch_all_wordpress_posts() と fetch_prtimes_feed() を削除 - タスク内にロジックをインライン化してシンプルな構造に変更 - PR TIMES RSS 取得の rescue を削除し、Fail-Fast 原則を実装 - エラー時は即座にタスク停止、部分的に壊れたデータでの継続を防止 - TASK_LOGGER の構文エラーを修正(括弧の適切な配置)
1 parent 2e74509 commit caae802

File tree

1 file changed

+67
-94
lines changed

1 file changed

+67
-94
lines changed

lib/tasks/news.rake

Lines changed: 67 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,24 @@ require 'rss'
22
require 'net/http'
33
require 'json'
44

5+
PR_TIMES_FEED = 'https://prtimes.jp/companyrdf.php?company_id=38935'.freeze
6+
DOJO_NEWS_FEED = 'https://news.coderdojo.jp/feed/'.freeze
7+
TEST_NEWS_FEED = Rails.root.join('spec', 'fixtures', 'sample_news.rss').freeze
8+
59
NEWS_YAML_PATH = 'db/news.yml'.freeze
6-
NEWS_LOG_PATH = 'log/news.log'.freeze
10+
NEWS_LOGS_PATH = 'log/news.log'.freeze
11+
TASK_LOGGER = ActiveSupport::BroadcastLogger.new(
12+
ActiveSupport::Logger.new(NEWS_LOGS_PATH),
13+
ActiveSupport::Logger.new(STDOUT)
14+
)
715

816
namespace :news do
917
desc "RSS フィードを取得し、#{NEWS_YAML_PATH} に保存"
1018
task fetch: :environment do
1119
# ロガー設定(ファイル+コンソール出力)
12-
console = ActiveSupport::Logger.new(STDOUT)
13-
logger_file = ActiveSupport::Logger.new(NEWS_LOG_PATH)
14-
logger = ActiveSupport::BroadcastLogger.new(logger_file, console)
15-
16-
logger.info('==== START news:fetch ====')
20+
TASK_LOGGER.info('==== START news:fetch ====')
1721

1822
# 本番/開発環境では実フィード、それ以外(テスト環境など)ではテスト用フィード
19-
DOJO_NEWS_FEED = 'https://news.coderdojo.jp/feed/'
20-
PR_TIMES_FEED = 'https://prtimes.jp/companyrdf.php?company_id=38935'
21-
TEST_NEWS_FEED = Rails.root.join('spec', 'fixtures', 'sample_news.rss')
2223
RSS_FEED_LIST = (Rails.env.test? || Rails.env.staging?) ?
2324
[TEST_NEWS_FEED] :
2425
[DOJO_NEWS_FEED, PR_TIMES_FEED]
@@ -96,31 +97,66 @@ namespace :news do
9697
f.write(formatted_items.to_yaml)
9798
end
9899

99-
logger.info "✅ Wrote #{merged_items.size} items to #{NEWS_YAML_PATH} (#{created_items.size} new, #{updated_items.size} updated)"
100-
logger.info "==== END news:fetch ===="
101-
logger.info ""
100+
TASK_LOGGER.info "✅ Wrote #{merged_items.size} items to #{NEWS_YAML_PATH} (#{created_items.size} new, #{updated_items.size} updated)"
101+
TASK_LOGGER.info "==== END news:fetch ===="
102+
TASK_LOGGER.info ""
102103
end
103104

104105
desc "news.yml をリセットし、すべてのフィードから全記事を取得"
105106
task 'fetch:reset' => :environment do
106107
# ロガー設定(ファイル+コンソール出力)
107-
console = ActiveSupport::Logger.new(STDOUT)
108-
logger_file = ActiveSupport::Logger.new(NEWS_LOG_PATH)
109-
logger = ActiveSupport::BroadcastLogger.new(logger_file, console)
110-
111-
logger.info('==== START news:fetch:reset ====')
108+
TASK_LOGGER.info('==== START news:fetch:reset ====')
112109

113110
# 1. news.yml を空にする
114111
File.write(NEWS_YAML_PATH, [].to_yaml)
115-
logger.info("📄 news.yml をリセットしました")
112+
TASK_LOGGER.info("📄 news.yml をリセットしました")
116113

117114
# 2. WordPress REST API からすべての投稿を取得
118-
dojo_news_items = fetch_all_wordpress_posts(logger)
119-
logger.info("📰 news.coderdojo.jp から #{dojo_news_items.size} 件を取得")
115+
dojo_news_items = []
116+
page = 1
117+
per_page = 100
118+
119+
loop do
120+
uri = URI("https://news.coderdojo.jp/wp-json/wp/v2/posts")
121+
uri.query = URI.encode_www_form(page: page, per_page: per_page, status: 'publish')
122+
123+
response = Net::HTTP.get_response(uri)
124+
break unless response.is_a?(Net::HTTPSuccess)
125+
126+
posts = JSON.parse(response.body)
127+
break if posts.empty?
128+
129+
posts.each do |post|
130+
dojo_news_items << {
131+
'url' => post['link'],
132+
'title' => post['title']['rendered'],
133+
'published_at' => Time.parse(post['date_gmt'] + ' UTC').iso8601
134+
}
135+
end
136+
137+
TASK_LOGGER.info("📄 WordPress API: ページ #{page} から #{posts.size} 件取得")
138+
page += 1
139+
end
140+
TASK_LOGGER.info("📰 news.coderdojo.jp から #{dojo_news_items.size} 件を取得")
120141

121142
# 3. PR TIMES RSS フィードからすべてのプレスリリースを取得
122-
prtimes_items = fetch_prtimes_feed(logger)
123-
logger.info("📢 PR TIMES から #{prtimes_items.size} 件を取得")
143+
prtimes_items = []
144+
feed = RSS::Parser.parse('https://prtimes.jp/companyrdf.php?company_id=38935', false)
145+
feed.items.each do |item|
146+
published_at = if item.respond_to?(:dc_date) && item.dc_date
147+
item.dc_date.iso8601
148+
else
149+
raise "PR TIMES feed: dc:date not found for item: #{item.link}"
150+
end
151+
152+
prtimes_items << {
153+
'url' => item.link,
154+
'title' => item.title,
155+
'published_at' => published_at
156+
}
157+
end
158+
TASK_LOGGER.info("📢 PR TIMES RSS: #{prtimes_items.size} 件取得")
159+
TASK_LOGGER.info("📢 PR TIMES から #{prtimes_items.size} 件を取得")
124160

125161
# 4. すべてのアイテムをマージし、ID を付与
126162
all_items = (dojo_news_items + prtimes_items).sort_by { |item|
@@ -133,7 +169,7 @@ namespace :news do
133169
end
134170

135171
# 最新順にソート
136-
sorted_items = all_items.sort_by { |item|
172+
sorted_items = all_items.sort_by { |item|
137173
Time.parse(item['published_at'])
138174
}.reverse
139175

@@ -151,78 +187,15 @@ namespace :news do
151187
f.write(formatted_items.to_yaml)
152188
end
153189

154-
logger.info("✅ 合計 #{sorted_items.size} 件を news.yml に保存しました")
155-
logger.info("📌 次は 'bundle exec rails news:upsert' でデータベースに反映してください")
156-
logger.info("==== END news:fetch:reset ====")
190+
TASK_LOGGER.info("✅ 合計 #{sorted_items.size} 件を news.yml に保存しました")
191+
TASK_LOGGER.info("📌 次は 'bundle exec rails news:upsert' でデータベースに反映してください")
192+
TASK_LOGGER.info("==== END news:fetch:reset ====")
157193
end
158194

159-
# WordPress REST API からすべての投稿を取得
160-
def fetch_all_wordpress_posts(logger)
161-
items = []
162-
page = 1
163-
per_page = 100
164-
165-
loop do
166-
uri = URI("https://news.coderdojo.jp/wp-json/wp/v2/posts")
167-
uri.query = URI.encode_www_form(page: page, per_page: per_page, status: 'publish')
168-
169-
response = Net::HTTP.get_response(uri)
170-
break unless response.is_a?(Net::HTTPSuccess)
171-
172-
posts = JSON.parse(response.body)
173-
break if posts.empty?
174-
175-
posts.each do |post|
176-
items << {
177-
'url' => post['link'],
178-
'title' => post['title']['rendered'],
179-
'published_at' => Time.parse(post['date_gmt'] + ' UTC').iso8601
180-
}
181-
end
182-
183-
logger.info("📄 WordPress API: ページ #{page} から #{posts.size} 件取得")
184-
page += 1
185-
end
186-
187-
items
188-
end
189-
190-
# PR TIMES RSS フィードから全記事を取得
191-
def fetch_prtimes_feed(logger)
192-
items = []
193-
194-
begin
195-
feed = RSS::Parser.parse('https://prtimes.jp/companyrdf.php?company_id=38935', false)
196-
197-
feed.items.each do |item|
198-
published_at = if item.respond_to?(:dc_date) && item.dc_date
199-
item.dc_date.iso8601
200-
else
201-
raise "PR TIMES feed: dc:date not found for item: #{item.link}"
202-
end
203-
204-
items << {
205-
'url' => item.link,
206-
'title' => item.title,
207-
'published_at' => published_at
208-
}
209-
end
210-
211-
logger.info("📢 PR TIMES RSS: #{items.size} 件取得")
212-
rescue => e
213-
logger.error("❌ PR TIMES フィード取得エラー: #{e.message}")
214-
end
215-
216-
items
217-
end
218195

219196
desc "#{NEWS_YAML_PATH} からデータベースに upsert"
220197
task upsert: :environment do
221-
console = ActiveSupport::Logger.new(STDOUT)
222-
logger_file = ActiveSupport::Logger.new(NEWS_LOG_PATH)
223-
logger = ActiveSupport::BroadcastLogger.new(logger_file, console)
224-
225-
logger.info "==== START news:upsert ===="
198+
TASK_LOGGER.info "==== START news:upsert ===="
226199

227200
news_items = YAML.safe_load File.read(NEWS_YAML_PATH)
228201
created_count = 0
@@ -244,13 +217,13 @@ namespace :news do
244217
created_count += 1 if is_new_record
245218
updated_count += 1 unless is_new_record
246219

247-
logger.info "[News] #{news.published_at.to_date} #{news.title} (#{status})"
220+
TASK_LOGGER.info "[News] #{news.published_at.to_date} #{news.title} (#{status})"
248221
end
249222
end
250223
end
251224

252-
logger.info "Upserted #{created_count + updated_count} items (#{created_count} new, #{updated_count} updated)."
253-
logger.info "==== END news:upsert ===="
254-
logger.info ""
225+
TASK_LOGGER.info "Upserted #{created_count + updated_count} items (#{created_count} new, #{updated_count} updated)."
226+
TASK_LOGGER.info "==== END news:upsert ===="
227+
TASK_LOGGER.info ""
255228
end
256229
end

0 commit comments

Comments
 (0)