Skip to content

Commit 9a70ba4

Browse files
authored
Merge pull request #1774 from coderdojo-japan/add-news-index-page
✉️ /news ページを追加してニュース記事一覧を表示
2 parents 98d428b + 5964b03 commit 9a70ba4

File tree

12 files changed

+214
-87
lines changed

12 files changed

+214
-87
lines changed

app/controllers/news_controller.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class NewsController < ApplicationController
2+
def index
3+
@title = '☯️ CoderDojo ニュース 📰'
4+
@desc = 'CoderDojo に関するお知らせの一覧ページです。'
5+
@url = request.url
6+
7+
# データベースからニュースデータを取得(最新順)
8+
@news_items = News.recent
9+
end
10+
end

app/helpers/application_helper.rb

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def prefecture_name_in_english(prefecture_name)
107107
# 都道府県名の英語表記を返す簡易マッピング
108108
# 「都」「府」「県」を除去してから検索
109109
name_without_suffix = prefecture_name.gsub(/[都府県]$/, '')
110-
110+
111111
prefecture_names = {
112112
'北海道' => 'Hokkaido',
113113
'青森' => 'Aomori',
@@ -157,7 +157,7 @@ def prefecture_name_in_english(prefecture_name)
157157
'鹿児島' => 'Kagoshima',
158158
'沖縄' => 'Okinawa'
159159
}
160-
160+
161161
prefecture_names[name_without_suffix] || prefecture_name
162162
end
163163

@@ -208,32 +208,8 @@ def translate_dojo_tag(tag_name)
208208
'HTML' => 'HTML',
209209
'CSS' => 'CSS'
210210
}
211-
212-
tag_translations[tag_name] || tag_name
213-
end
214211

215-
def format_news_title(news)
216-
has_custom_emoji = news.title[0]&.match?(/[\p{Emoji}&&[^0-9#*]]/)
217-
return news.title if has_custom_emoji
218-
219-
# Add preset Emoji to its prefix if news.title does not have Emoji.
220-
emoji = case news.url
221-
when %r{/podcasts/\d+}
222-
'📻'
223-
when %r{prtimes\.jp}
224-
'📢'
225-
else
226-
'📰'
227-
end
228-
"#{emoji} #{news.title}"
212+
tag_translations[tag_name] || tag_name
229213
end
230214

231-
def news_link_url(news)
232-
# Convert absolute podcast URLs to relative paths for local development
233-
if news.url.match?(%r{^https://coderdojo\.jp/podcasts/\d+$})
234-
news.url.sub('https://coderdojo.jp', '')
235-
else
236-
news.url
237-
end
238-
end
239215
end

app/models/news.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,29 @@ class News < ApplicationRecord
66
uniqueness: true,
77
format: { with: /\Ahttps?:\/\/.*\z/i }
88
validates :published_at, presence: true
9+
10+
def formatted_title
11+
has_custom_emoji = title[0]&.match?(/[\p{Emoji}&&[^0-9#*]]/)
12+
return title if has_custom_emoji
13+
14+
# Add preset Emoji to its prefix if title does not have Emoji.
15+
emoji = case url
16+
when %r{/podcasts/\d+}
17+
'📻'
18+
when %r{prtimes\.jp}
19+
'📢'
20+
else
21+
'📰'
22+
end
23+
"#{emoji} #{title}"
24+
end
25+
26+
def link_url
27+
# Convert absolute podcast URLs to relative paths for local development
28+
if url.match?(%r{^https://coderdojo\.jp/podcasts/\d+$})
29+
url.sub('https://coderdojo.jp', '')
30+
else
31+
url
32+
end
33+
end
934
end

app/views/home/show.html.erb

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -194,30 +194,15 @@
194194
<ul class="list" style="list-style: none;">
195195
<% @news_items.each do |news| %>
196196
<li>
197-
<%= link_to format_news_title(news), news_link_url(news), target: '_blank' %>
197+
<%= link_to news.formatted_title, news.link_url, target: '_blank' %>
198198
</li>
199199
<% end %>
200200
</ul>
201-
<p style="margin-top: 30px;">
202-
最新情報はメールで受け取れます。
203-
<br class="ignore-pc">
204-
<small>(毎月配信)</small>
205-
</p>
206-
207-
<div id="mc_embed_signup">
208-
<form id="mc-embedded-subscribe-form" class="validate" action="https://coderdojo.us17.list-manage.com/subscribe/post?u=39a5824e42ab56ec44bb4e84e&amp;id=097dfa6a14" method="post" name="mc-embedded-subscribe-form" novalidate="" target="_blank">
209-
<div id="mc_embed_signup_scroll">
210-
<input id="mce-EMAIL" type="email" name="EMAIL" class="email" placeholder="your@example.com">
211-
<div style="position: absolute; left: -5000px;" aria-hidden="true">
212-
<input tabindex="-1" name="b_39a5824e42ab56ec44bb4e84e_097dfa6a14" type="text" value="">
213-
</div>
214-
<input id="mc-embedded-subscribe" class="button" name="subscribe" type="submit" value="購読する">
215-
</div>
216-
</form>
217-
</div>
201+
202+
<%= render 'shared/dojo_letter_signup' %>
218203

219204
<div class="btn-cover" style="margin-top: 40px;">
220-
<a class="btn-blue" href="<%= news_url %>">
205+
<a class="btn-blue" href="<%= news_index_path %>">
221206
<i class="far fa-newspaper"></i>
222207
過去の記事を読む
223208
</a>

app/views/news/index.html.erb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<% provide :title, strip_tags(@title) %>
2+
<% provide :desc, strip_tags(@desc) %>
3+
<% provide :url, @url %>
4+
<% provide :meta_image, "/img/ogp-news.jpeg" %>
5+
6+
<div class='container'>
7+
<section class='news' style='padding: 50px 0px 0px;'>
8+
<h2 class='text-center'><%= @title.html_safe %></h2>
9+
10+
<p class='text-center' style='padding-top: 30px;'>
11+
<%= @desc.html_safe %>
12+
</p>
13+
</section>
14+
15+
<section class="text-center list" style='margin-bottom: 30px;'>
16+
<%= render 'shared/dojo_letter_signup' %>
17+
<%= render 'shared/social_buttons' %>
18+
</section>
19+
20+
<section class='news' style='padding: 50px 0px;'>
21+
<% if @news_items.any? %>
22+
<div class="news-list">
23+
<% @news_items.each do |news| %>
24+
<article class="news-item" style="margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px solid #e0e0e0;">
25+
<h3 style="margin-bottom: 10px;">
26+
<%= link_to news.formatted_title, news.link_url, target: '_blank', rel: 'noopener' %>
27+
</h3>
28+
<p class="news-meta" style="color: #666; font-size: 14px;">
29+
<i class="fa fa-calendar"></i>
30+
<%= l(news.published_at.to_date, format: :long) if news.published_at %>
31+
</p>
32+
</article>
33+
<% end %>
34+
</div>
35+
<% else %>
36+
<p class="text-center">現在、ニュース記事はありません。</p>
37+
<% end %>
38+
</section>
39+
40+
<section class="text-center list" style='margin-bottom: 100px;'>
41+
<%= render 'shared/dojo_letter_signup' %>
42+
<%= render 'shared/social_buttons' %>
43+
</section>
44+
</div>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<p style="margin-top: 30px;">
2+
最新情報はメールで受け取れます。
3+
<br class="ignore-pc">
4+
<small>(毎月配信)</small>
5+
</p>
6+
7+
<div id="mc_embed_signup">
8+
<form id="mc-embedded-subscribe-form" class="validate" action="https://coderdojo.us17.list-manage.com/subscribe/post?u=39a5824e42ab56ec44bb4e84e&amp;id=097dfa6a14" method="post" name="mc-embedded-subscribe-form" novalidate="" target="_blank">
9+
<div id="mc_embed_signup_scroll">
10+
<input id="mce-EMAIL" type="email" name="EMAIL" class="email" placeholder="your@example.com">
11+
<div style="position: absolute; left: -5000px;" aria-hidden="true">
12+
<input tabindex="-1" name="b_39a5824e42ab56ec44bb4e84e_097dfa6a14" type="text" value="">
13+
</div>
14+
<input id="mc-embedded-subscribe" class="button" name="subscribe" type="submit" value="購読する">
15+
</div>
16+
</form>
17+
</div>

app/views/shared/_footer.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<h2 style="line-height: 30px;">
33
<a class="footer-link" href="/" title="トップページに戻ります">Top</a>
44
| <a class="footer-link" href="/kata" title="道場情報まとめ「Kata」を見る">Kata</a>
5-
| <a class="footer-link" href="/#news" title="最近のニュース「DojoLetter」を見る">News</a>
5+
| <a class="footer-link" href="/news" title="最近のニュース「DojoLetter」を見る">News</a>
66
| <a class="footer-link" href="/docs" title="公式資料まとめ「Docs」を見る">資料</a>
77
| <a class="footer-link" href="/charter" title="CoderDojo 憲章を見る">憲章</a>
88
| <a class="footer-link" href="/stats" title="CoderDojo の統計データを見る">統計</a>
@@ -16,7 +16,7 @@
1616
</h2>
1717

1818
<h2>
19-
<%= link_to news_url do %>
19+
<%= link_to news_index_path do %>
2020
<i class="fa fa-newspaper-o fa-3x fa-fw" aria-hidden="true" title="News"></i>
2121
<% end %>
2222
<%= link_to facebook_page_url do %>

app/views/shared/_header.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<%= link_to '最近の活動', '/#news' %>
2222
<span class="navbar-dd-l"></span>
2323
<ul class="navbar-dd">
24-
<li><%= link_to '📰 News', '/#news' %></li>
24+
<li><%= link_to '📰 News', news_index_path %></li>
2525
<li><%= link_to '📻 Podcast', '/podcasts' %></li>
2626
<li><%= link_to '📺 YouTube', '/youtube' %></li>
2727
<li><%= link_to '📚 その他', '/#kata' %></li>

config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
end
7575
end
7676
resources :docs, only: %i(index show)
77+
resources :news, only: %i(index)
7778
resources :podcasts, only: %i(index show)
7879
resources :spaces, only: %i(index)
7980

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,6 @@
11
require 'rails_helper'
22

33
RSpec.describe ApplicationHelper, type: :helper do
4-
describe '#format_news_title' do
5-
it '先頭文字が絵文字ならそのまま返す' do
6-
news = double('news', title: '🔔 新着', url: 'https://news.coderdojo.jp/123')
7-
expect(helper.format_news_title(news)).to eq '🔔 新着'
8-
end
9-
10-
context '先頭文字が絵文字でない場合' do
11-
it 'ポッドキャストのURLには📻を付与する' do
12-
news = double('news', title: 'エピソード33', url: 'https://coderdojo.jp/podcasts/33')
13-
expect(helper.format_news_title(news)).to eq '📻 エピソード33'
14-
end
15-
16-
it 'PR TIMESのURLには📢を付与する' do
17-
news = double('news', title: 'プレスリリース', url: 'https://prtimes.jp/main/html/rd/p/000000001.000038935.html')
18-
expect(helper.format_news_title(news)).to eq '📢 プレスリリース'
19-
end
20-
21-
it 'その他のURLには📰を付与する' do
22-
news = double('news', title: '更新情報', url: 'https://news.coderdojo.jp/2025/12/06/dojoletter')
23-
expect(helper.format_news_title(news)).to eq '📰 更新情報'
24-
end
25-
end
26-
end
27-
28-
describe '#news_link_url' do
29-
it 'ポッドキャストの絶対URLを相対パスに変換する' do
30-
news = double('news', url: 'https://coderdojo.jp/podcasts/33')
31-
expect(helper.news_link_url(news)).to eq '/podcasts/33'
32-
end
33-
34-
it 'その他のURLはそのまま返す' do
35-
news = double('news', url: 'https://news.coderdojo.jp/2025/12/06/dojoletter')
36-
expect(helper.news_link_url(news)).to eq 'https://news.coderdojo.jp/2025/12/06/dojoletter'
37-
38-
news2 = double('news', url: 'https://prtimes.jp/main/html/rd/p/000000001.000038935.html')
39-
expect(helper.news_link_url(news2)).to eq 'https://prtimes.jp/main/html/rd/p/000000001.000038935.html'
40-
end
41-
end
4+
# News関連のメソッドはNewsモデルに移動しました
5+
# spec/models/news_spec.rb を参照
426
end

0 commit comments

Comments
 (0)