Skip to content

トップページの news セクションを RSS から自動生成 #1704

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
92dd480
feat: RSSフィードチェックタスクを追加
nacchan99 Jun 26, 2025
2a9c1f2
ci: news:fetchタスクを毎朝9:00 JSTに実行するワークフローを追加
nacchan99 Jun 26, 2025
711eabe
Newsモデルとマイグレーション、テストファイルを追加
nacchan99 Jun 30, 2025
0f45187
ニュース YAML→DB インポートタスクを追加&news.yml を初期化
nacchan99 Jul 1, 2025
66f64e1
Release Phaseに ニュースポイントを追加
nacchan99 Jul 1, 2025
dfceb2f
fetch_newsタスクのフィードURLを https://coderdojo.jp/#news に修正
nacchan99 Jul 1, 2025
4030fa4
feat:fetch_newsタスクのフィードURLを https://news.coderdojo.jp/feed/ に修正
nacchan99 Jul 3, 2025
98b657e
feat: ニュースセクションをDBからの動的表示に切り替え
nacchan99 Jul 7, 2025
c5e4b24
refactor: ニュース絵文字の判定ロジックを改善
nacchan99 Jul 7, 2025
88358e8
テストが通らない問題を解消するため origin/main の変更をマージ
nacchan99 Jul 8, 2025
aa79f4a
refactor: ニュース表示ロジックを改善
nacchan99 Jul 9, 2025
f995b08
test: サンプルニュースに絵文字ありのテストケースを追加
nacchan99 Jul 10, 2025
2200d6b
fix: 不要な改行を削除
nacchan99 Jul 14, 2025
46e7e97
fix: 不要なスペースを削除
nacchan99 Jul 14, 2025
4974b01
refactor: ニュース取得ロジックをモデルに移動
nacchan99 Jul 14, 2025
f577bcb
ワークフローをブランチでも実行
nacchan99 Jul 14, 2025
0fe9433
chore: update news.yml via GitHub Actions
github-actions[bot] Jul 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/fetch_news.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Fetch News

on:
schedule:
# 毎朝 9:00 JST
- cron: '0 0 * * *'
workflow_dispatch:
pull_request:
branches:
- "*"

jobs:
fetch:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version-file: .ruby-version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

以下が良さそうです👀

- ruby-version-file: .ruby-version
+ ruby-version: .ruby-version

bundler-cache: true

- name: Install dependencies
run: bundle install --jobs 4 --retry 3

- name: Run news:fetch task
run: bin/rails news:fetch

- name: Commit updated news.yml
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add db/news.yml
if ! git diff --cached --quiet; then
git commit -m "chore: update news.yml via GitHub Actions"
git push
else
echo "No changes in db/news.yml"
fi
1 change: 1 addition & 0 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ def show
@dojo_count = Dojo.active_dojos_count
@regions_and_dojos = Dojo.group_by_region_on_active
@prefectures_and_dojos = Dojo.group_by_prefecture_on_active
@news_items = News.recent.limit(7)
end
end
4 changes: 4 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,8 @@ def translate_dojo_tag(tag_name)
tag_translations[tag_name] || tag_name
end

def format_news_title(news)
has_emoji = news.title[0]&.match?(/[\p{Emoji}&&[^0-9#*]]/)
has_emoji ? news.title : "📰 #{news.title}"
end
end
3 changes: 3 additions & 0 deletions app/models/news.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class News < ApplicationRecord
scope :recent, -> { order(published_at: :desc) }
end
26 changes: 5 additions & 21 deletions app/views/home/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -177,27 +177,11 @@
</h2>
<br>
<ul class="list" style="list-style: none;">
<li>💻
<%= link_to '米国系IT企業からCoderDojoへ、55台のノートPC寄贈', news_url('/2025/04/04/55-laptops-to-coderdojo/') %>
</li>
<li>📰
<%= link_to 'DojoLetter Vol.81 2025年01月号', news_url('/2025/03/10/dojoletter-vol-82-2025年01月号/') %>
</li>
<li>🎲
<%= link_to 'ダイス×プログラミング『ニャイス!コード』 を75台寄贈', news_url('/2025/02/14/coderdojo-de-nyaicecode/') %>
</li>
<li>📰
<%= link_to 'DojoLetter Vol.80 2024年12月号', news_url('/2025/02/10/dojoletter-vol-80-2024年12月号/') %>
</li>
<li>📰
<%= link_to 'DojoLetter Vol.79 2024年11月号', news_url('/2025/01/14/dojoletter-vol-79-2024年11月号/') %>
</li>
<li>🎄
<%= link_to '128台のノートPC寄贈、Box JapanからCoderDojoへ', news_url('/2024/12/25/box-japan-to-coderdojo/') %>
</li>
<li>📰
<%= link_to 'DojoLetter Vol.78 2024年10月号', news_url('/2024/12/10/dojoletter-vol-78-2024年10月号/') %>
</li>
<% @news_items.each do |news| %>
<li>
<%= link_to format_news_title(news), news.url, target: '_blank', rel: 'noopener noreferrer' %>
</li>
<% end %>
</ul>
<p style="margin-top: 30px;">
最新情報はメールで受け取れます。
Expand Down
13 changes: 13 additions & 0 deletions db/migrate/20250630040611_create_news.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CreateNews < ActiveRecord::Migration[8.0]
def change
create_table :news do |t|
t.string :title
t.string :url
t.datetime :published_at

t.timestamps
end

add_index :news, :url, unique: true
end
end
42 changes: 42 additions & 0 deletions db/news.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
news:
- url: https://news.coderdojo.jp/2024/12/25/box-japan-to-coderdojo/
title: "\U0001F384128台のノート PC 寄贈、Box Japan から CoderDojo へ \U0001F381"
published_at: Wed, 25 Dec 2024 11:00:40 +0000
id: https://news.coderdojo.jp/2024/12/25/box-japan-to-coderdojo/
- url: https://news.coderdojo.jp/2025/01/14/dojoletter-vol-79-2024%e5%b9%b411%e6%9c%88%e5%8f%b7/
title: DojoLetter Vol.79 2024年11月号
published_at: Tue, 14 Jan 2025 03:30:45 +0000
id: https://news.coderdojo.jp/2025/01/14/dojoletter-vol-79-2024%e5%b9%b411%e6%9c%88%e5%8f%b7/
- url: https://news.coderdojo.jp/2025/06/10/dojoletter-vol-85-2025%e5%b9%b404%e6%9c%88%e5%8f%b7/
title: DojoLetter Vol.85 2025年04月号
published_at: Tue, 10 Jun 2025 03:30:18 +0000
id: https://news.coderdojo.jp/2025/06/10/dojoletter-vol-85-2025%e5%b9%b404%e6%9c%88%e5%8f%b7/
- url: https://news.coderdojo.jp/2025/07/10/dojoletter-vol-86-2025%e5%b9%b405%e6%9c%88%e5%8f%b7/
title: DojoLetter Vol.86 2025年05月号
published_at: Thu, 10 Jul 2025 04:00:07 +0000
id: https://news.coderdojo.jp/2025/07/10/dojoletter-vol-86-2025%e5%b9%b405%e6%9c%88%e5%8f%b7/
- url: https://news.coderdojo.jp/2025/04/10/dojoletter-vol-83-2025%e5%b9%b402%e6%9c%88%e5%8f%b7/
title: DojoLetter Vol.83 2025年02月号
published_at: Thu, 10 Apr 2025 03:45:27 +0000
id: https://news.coderdojo.jp/2025/04/10/dojoletter-vol-83-2025%e5%b9%b402%e6%9c%88%e5%8f%b7/
- url: https://news.coderdojo.jp/2025/05/12/dojoletter-vol-84-2025%e5%b9%b403%e6%9c%88%e5%8f%b7/
title: DojoLetter Vol.84 2025年03月号
published_at: Mon, 12 May 2025 04:00:33 +0000
id: https://news.coderdojo.jp/2025/05/12/dojoletter-vol-84-2025%e5%b9%b403%e6%9c%88%e5%8f%b7/
- url: https://news.coderdojo.jp/2025/03/10/dojoletter-vol-82-2025%e5%b9%b401%e6%9c%88%e5%8f%b7/
title: DojoLetter Vol.82 2025年01月号
published_at: Mon, 10 Mar 2025 04:00:33 +0000
id: https://news.coderdojo.jp/2025/03/10/dojoletter-vol-82-2025%e5%b9%b401%e6%9c%88%e5%8f%b7/
- url: https://news.coderdojo.jp/2025/02/10/dojoletter-vol-80-2024%e5%b9%b412%e6%9c%88%e5%8f%b7/
title: DojoLetter Vol.80 2024年12月号
published_at: Mon, 10 Feb 2025 04:00:55 +0000
id: https://news.coderdojo.jp/2025/02/10/dojoletter-vol-80-2024%e5%b9%b412%e6%9c%88%e5%8f%b7/
- url: https://news.coderdojo.jp/2025/02/14/coderdojo-de-nyaicecode/
title: "\U0001F3B2 ダイス×プログラミング『ニャイス!コード』を、CoderDojo に75台寄贈"
published_at: Fri, 14 Feb 2025 08:24:07 +0000
id: https://news.coderdojo.jp/2025/02/14/coderdojo-de-nyaicecode/
- url: https://news.coderdojo.jp/2025/04/04/55-laptops-to-coderdojo/
title: 米国系 IT 企業から CoderDojo へ、55 台のノート PC 寄贈
published_at: Fri, 04 Apr 2025 10:00:32 +0000
id: https://news.coderdojo.jp/2025/04/04/55-laptops-to-coderdojo/
13 changes: 11 additions & 2 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2025_05_20_091834) do
ActiveRecord::Schema[8.0].define(version: 2025_06_30_040611) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
enable_extension "pg_stat_statements"
enable_extension "plpgsql"

create_table "dojo_event_services", id: :serial, force: :cascade do |t|
t.integer "dojo_id", null: false
Expand Down Expand Up @@ -58,6 +58,15 @@
t.index ["service_name", "event_id"], name: "index_event_histories_on_service_name_and_event_id", unique: true
end

create_table "news", force: :cascade do |t|
t.string "title"
t.string "url"
t.datetime "published_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["url"], name: "index_news_on_url", unique: true
end

create_table "podcasts", force: :cascade do |t|
t.string "enclosure_url", null: false
t.string "title", null: false
Expand Down
62 changes: 62 additions & 0 deletions lib/tasks/fetch_news.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require 'rss'
require 'open-uri'
require 'yaml'
require 'active_support/broadcast_logger'

namespace :news 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:fetch ====')

# テスト/ステージング環境ではサンプルファイル、本番は実サイトのフィード
feed_urls = if Rails.env.test? || Rails.env.staging?
[Rails.root.join('spec', 'fixtures', 'sample_news.rss').to_s]
else
[
'https://news.coderdojo.jp/feed/',
# 必要に応じて他 Dojo の RSS もここに追加可能
# 'https://coderdojotokyo.org/feed',
]
end

# RSS 取得&パース
items = feed_urls.flat_map do |url|
logger.info("Fetching RSS → #{url}")
begin
URI.open(url) do |rss|
feed = RSS::Parser.parse(rss, false)
feed.items.map do |item|
{
'url' => item.link,
'title' => item.title,
'published_at' => item.pubDate.to_s
}
end
end
rescue => e
logger.warn("⚠️ Failed to fetch #{url}: #{e.message}")
[]
end
end

# 重複排除&日付降順ソート
unique = items.uniq { |i| i['url'] }
sorted = unique.sort_by { |i| i['published_at'] }.reverse

# id を追加
sorted.each { |i| i['id'] = i['url'] }

# YAML に書き出し
File.open('db/news.yml', 'w') do |f|
f.write({ 'news' => sorted }.to_yaml)
end

logger.info("✅ Wrote #{sorted.size} items to db/news.yml")
logger.info('==== END news:fetch ====')
end
end
24 changes: 24 additions & 0 deletions lib/tasks/import_news.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'yaml'

namespace :news do
desc "db/news.yml を読み込んで News テーブルを upsert する"
task import_from_yaml: :environment do
yaml_path = Rails.root.join('db', 'news.yml')
raw = YAML.load_file(yaml_path)

# entries を計算
entries = raw['news'] || []

entries.each do |attrs|
news = News.find_or_initialize_by(url: attrs['url'])
news.assign_attributes(
title: attrs['title'],
published_at: attrs['published_at']
)
news.save!
puts "[news] #{news.published_at.to_date} #{news.title}"
end

puts "Imported #{entries.size} items."
end
end
1 change: 1 addition & 0 deletions script/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +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 dojo_event_services:upsert
bundle exec rails podcasts:upsert
7 changes: 7 additions & 0 deletions spec/factories/news.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FactoryBot.define do
factory :news do
title { "MyString" }
url { "MyString" }
published_at { "2025-06-30 13:06:11" }
end
end
30 changes: 30 additions & 0 deletions spec/fixtures/sample_news.rss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Sample News Feed</title>
<link>https://coderdojo.jp/</link>
<description>テスト用のサンプルニュースフィード</description>

<item>
<title>テスト記事①</title>
<link>https://example.com/articles/1</link>
<pubDate>Mon, 01 Jun 2025 10:00:00 +0900</pubDate>
<description>サンプル記事の本文①</description>
</item>

<item>
<title>テスト記事②</title>
<link>https://example.com/articles/2</link>
<pubDate>Tue, 02 Jun 2025 11:30:00 +0900</pubDate>
<description>サンプル記事の本文②</description>
</item>

<item>
<title>🎉 テスト記事③</title>
<link>https://example.com/articles/3</link>
<pubDate>Wed, 03 Jun 2025 12:00:00 +0900</pubDate>
<description>絵文字ありのサンプル記事の本文③</description>
</item>

</channel>
</rss>
5 changes: 5 additions & 0 deletions spec/models/news_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require 'rails_helper'

RSpec.describe News, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end