@@ -61,24 +61,21 @@ def fetch_prtimes_posts(rss_feed_url)
6161end
6262
6363namespace :news do
64- desc "RSS フィードを取得し 、#{ NEWS_YAML_PATH } に保存 "
64+ desc "ニュースフィードを取得し 、#{ NEWS_YAML_PATH } を再構築(冪等) "
6565 task fetch : :environment do
6666 # ロガー設定(ファイル+コンソール出力)
6767 TASK_LOGGER . info ( '==== START news:fetch ====' )
6868
69- # 本番/開発環境では実フィード、それ以外(テスト環境など)ではテスト用フィード
70- RSS_FEED_LIST = ( Rails . env . test? || Rails . env . staging? ) ?
71- [ TEST_NEWS_FEED ] :
72- [ DOJO_NEWS_FEED , PR_TIMES_FEED ]
73-
74- # RSS のデータ構造を、News のデータ構造に変換
75- fetched_items = RSS_FEED_LIST . flat_map do |feed |
76- feed = RSS ::Parser . parse ( feed , false )
77- feed . items . map { |item |
78- # RSS 1.0 (RDF) と RSS 2.0 の両方に対応
79- # RSS 2.0: pubDate, RSS 1.0 (RDF): dc:date
80- # - PR TIMES: RSS 1.0 (RDF) 形式 - <rdf:RDF> タグ、dc:date フィールドを使用
81- # - CoderDojo News: RSS 2.0 形式 - <rss version="2.0"> タグ、pubDate フィールドを使用
69+ # 1. news.yml を空にする
70+ File . write ( NEWS_YAML_PATH , [ ] . to_yaml )
71+ TASK_LOGGER . info ( "📄 news.yml をリセットしました" )
72+
73+ # 2. 環境に応じたデータソースから取得
74+ if Rails . env . test? || Rails . env . staging?
75+ # テスト環境: サンプルRSSのみ
76+ TASK_LOGGER . info ( "🧪 テスト環境: サンプルRSSから取得" )
77+ feed = RSS ::Parser . parse ( TEST_NEWS_FEED , false )
78+ items = feed . items . map { |item |
8279 published_at = if item . respond_to? ( :pubDate ) && item . pubDate
8380 item . pubDate
8481 elsif item . respond_to? ( :dc_date ) && item . dc_date
@@ -90,100 +87,32 @@ namespace :news do
9087 {
9188 'url' => item . link ,
9289 'title' => item . title ,
93- 'published_at' => published_at . in_time_zone ( 'Asia/Tokyo' ) . iso8601 # JST に統一
90+ 'published_at' => published_at . in_time_zone ( 'Asia/Tokyo' ) . iso8601
9491 }
9592 }
96- end
93+ else
94+ # 本番環境: WordPress REST API + PR TIMES RSS
95+ dojo_news_items = fetch_dojo_news_posts ( DOJO_NEWS_JSON )
96+ TASK_LOGGER . info ( "📰 news.coderdojo.jp から #{ dojo_news_items . size } 件を取得" )
9797
98- # 取得済みニュース (YAML) を読み込み、URL をキーとしたハッシュに変換
99- existing_items = YAML . safe_load ( File . read NEWS_YAML_PATH ) . index_by { it [ 'url' ] }
100- existing_max_id = existing_items . flat_map { |url , item | item [ 'id' ] . to_i } . max || 0
101-
102- # 新規記事と既存記事を分離
103- created_items = [ ]
104- updated_items = [ ]
105-
106- fetched_items . each do |fetched_item |
107- existing_item = existing_items [ fetched_item [ 'url' ] ]
108-
109- if existing_item . nil?
110- # 新規アイテムならそのまま追加
111- created_items << fetched_item
112- elsif existing_item [ 'title' ] != fetched_item [ 'title' ] || existing_item [ 'published_at' ] != fetched_item [ 'published_at' ]
113- # タイトルまたは公開日が変わっていたら更新
114- updated_items << existing_item . merge ( fetched_item )
115- end
116- end
98+ prtimes_items = fetch_prtimes_posts ( PR_TIMES_FEED )
99+ TASK_LOGGER . info ( "📢 PR TIMES から #{ prtimes_items . size } 件を取得" )
117100
118- # 新しいアイテムのみに ID を割り当て(古い順)
119- created_items . sort_by! { Time . parse it [ 'published_at' ] }
120- created_items . each . with_index ( 1 ) do |item , index |
121- item [ 'id' ] = existing_max_id + index
101+ items = dojo_news_items + prtimes_items
122102 end
123103
124- # URL をキーに、更新されなかった既存の YAML データを取得・保持
125- updated_urls = updated_items . map { it [ 'url' ] }
126- unchanged_items = existing_items . values . reject { updated_urls . include? ( it [ 'url' ] ) }
127-
128- # 新規・更新・既存の各アイテムをマージし、日付降順でソート
129- merged_items = ( unchanged_items + updated_items + created_items ) . sort_by {
130- Time . parse ( it [ 'published_at' ] )
131- } . reverse
132-
133- # YAML ファイルに書き出し
134- File . open ( NEWS_YAML_PATH , 'w' ) do |f |
135- formatted_items = merged_items . map do |item |
136- {
137- 'id' => item [ 'id' ] ,
138- 'url' => item [ 'url' ] ,
139- 'title' => item [ 'title' ] ,
140- 'published_at' => item [ 'published_at' ]
141- }
142- end
143-
144- f . write ( formatted_items . to_yaml )
145- end
146-
147- TASK_LOGGER . info "✅ Wrote #{ merged_items . size } items to #{ NEWS_YAML_PATH } (#{ created_items . size } new, #{ updated_items . size } updated)"
148- TASK_LOGGER . info "==== END news:fetch ===="
149- TASK_LOGGER . info ""
150- end
151-
152- desc "news.yml をリセットし、すべてのフィードから全記事を取得"
153- task 'fetch:reset' => :environment do
154- # ロガー設定(ファイル+コンソール出力)
155- TASK_LOGGER . info ( '==== START news:fetch:reset ====' )
156-
157- # 1. news.yml を空にする
158- File . write ( NEWS_YAML_PATH , [ ] . to_yaml )
159- TASK_LOGGER . info ( "📄 news.yml をリセットしました" )
160-
161- # 2. WordPress REST API からすべての投稿を取得
162- dojo_news_items = fetch_dojo_news_posts ( DOJO_NEWS_JSON )
163- TASK_LOGGER . info ( "📰 news.coderdojo.jp から #{ dojo_news_items . size } 件を取得" )
164-
165- # 3. PR TIMES RSS フィードからすべてのプレスリリースを取得
166- prtimes_items = fetch_prtimes_posts ( PR_TIMES_FEED )
167- TASK_LOGGER . info ( "📢 PR TIMES から #{ prtimes_items . size } 件を取得" )
168-
169- # 4. すべてのアイテムをマージし、ID を付与
170- all_items = ( dojo_news_items + prtimes_items ) . sort_by { |item |
171- Time . parse ( item [ 'published_at' ] )
172- }
173-
174- # ID を付与(古い順で1から)
175- all_items . each . with_index ( 1 ) do |item , index |
104+ # 3. 古い順でソートしてID付与(1から開始)
105+ sorted_items = items . sort_by { |item | Time . parse ( item [ 'published_at' ] ) }
106+ sorted_items . each . with_index ( 1 ) do |item , index |
176107 item [ 'id' ] = index
177108 end
178109
179- # 最新順にソート
180- sorted_items = all_items . sort_by { |item |
181- Time . parse ( item [ 'published_at' ] )
182- } . reverse
110+ # 4. 最新順にソート
111+ final_items = sorted_items . sort_by { |item | Time . parse ( item [ 'published_at' ] ) } . reverse
183112
184113 # 5. YAML ファイルに書き出し
185114 File . open ( NEWS_YAML_PATH , 'w' ) do |f |
186- formatted_items = sorted_items . map do |item |
115+ formatted_items = final_items . map do |item |
187116 {
188117 'id' => item [ 'id' ] ,
189118 'url' => item [ 'url' ] ,
@@ -195,9 +124,10 @@ namespace :news do
195124 f . write ( formatted_items . to_yaml )
196125 end
197126
198- TASK_LOGGER . info ( "✅ 合計 #{ sorted_items . size } 件を news.yml に保存しました" )
127+ TASK_LOGGER . info ( "✅ 合計 #{ final_items . size } 件を news.yml に保存しました" )
199128 TASK_LOGGER . info ( "📌 次は 'bundle exec rails news:upsert' でデータベースに反映してください" )
200- TASK_LOGGER . info ( "==== END news:fetch:reset ====" )
129+ TASK_LOGGER . info ( "==== END news:fetch ====" )
130+ TASK_LOGGER . info ( "" )
201131 end
202132
203133
0 commit comments