Skip to content

Commit d58e5f4

Browse files
committed
feat: 道場統計の年次フィルタリングとCSVダウンロード機能を実装
主な変更内容: - /dojos エンドポイントにCSV形式サポートを追加 - yearパラメータによる年末時点のアクティブ道場フィルタリング - 年選択UIとダウンロードボタンをHTMLビューに追加 機能詳細: - GET /dojos.csv → 全道場リスト(CSV形式) - GET /dojos?year=2020 → 2020年末時点のアクティブ道場(HTML) - GET /dojos.json?year=2020 → 同上(JSON形式) - GET /dojos.csv?year=2020 → 同上(CSV形式) エラーハンドリング: - 無効な年が指定された場合はフラッシュメッセージでエラーを表示 - 2012年から現在年までの範囲チェック実装 Closes #1373
1 parent 658583f commit d58e5f4

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

app/controllers/dojos_controller.rb

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
11
class DojosController < ApplicationController
22

3-
# GET /dojos[.json]
3+
# GET /dojos[.html|.json|.csv]
44
def index
5+
# yearパラメータがある場合の処理
6+
if params[:year].present?
7+
begin
8+
year = params[:year].to_i
9+
# 有効な年の範囲をチェック
10+
unless year.between?(2012, Date.current.year)
11+
flash[:alert] = "指定された年(#{year})は無効です。2012年から#{Date.current.year}年の間で指定してください。"
12+
return redirect_to dojos_path
13+
end
14+
15+
@selected_year = year
16+
end_of_year = Time.zone.local(@selected_year).end_of_year
17+
18+
# その年末時点でアクティブだった道場を取得
19+
dojos_scope = Dojo.active_at(end_of_year)
20+
@page_title = "#{@selected_year}年末時点のCoderDojo一覧"
21+
rescue ArgumentError
22+
flash[:alert] = "無効な年が指定されました"
23+
return redirect_to dojos_path
24+
end
25+
else
26+
# yearパラメータなしの場合(既存の実装そのまま)
27+
dojos_scope = Dojo.all
28+
end
29+
530
@dojos = []
6-
Dojo.includes(:prefecture).order(order: :asc).all.each do |dojo|
31+
dojos_scope.includes(:prefecture).order(order: :asc).each do |dojo|
732
@dojos << {
833
id: dojo.id,
934
url: dojo.url,
@@ -19,10 +44,9 @@ def index
1944
end
2045

2146
respond_to do |format|
22-
# No corresponding View for now.
23-
# Only for API: GET /dojos.json
24-
format.html # => app/views/dojos/index.html.erb
47+
format.html { render :index } # => app/views/dojos/index.html.erb
2548
format.json { render json: @dojos }
49+
format.csv { send_data render_to_string, type: :csv }
2650
end
2751
end
2852

app/views/dojos/index.csv.ruby

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
require 'csv'
2+
3+
csv_data = CSV.generate do |csv|
4+
# ヘッダー行
5+
csv << ['ID', '道場名', '都道府県', 'URL', '設立日', '状態']
6+
7+
# データ行
8+
@dojos.each do |dojo|
9+
csv << [
10+
dojo[:id],
11+
dojo[:name],
12+
dojo[:prefecture],
13+
dojo[:url],
14+
dojo[:created_at].strftime("%F"),
15+
dojo[:is_active] ? 'アクティブ' : '非アクティブ'
16+
]
17+
end
18+
end

app/views/dojos/index.html.erb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,49 @@
2121
<li>現在は活動停止中 (In-active) の道場も表示されています</li>
2222
<li>道場名をクリックすると個別の統計データが確認できます</li>
2323
<li>下記表は <code><%= link_to dojos_path(format: :json), dojos_path(format: :json) %></code> で JSON に変換できます</li>
24+
<li>CSV形式でもダウンロード可能です <code><%= link_to dojos_path(format: :csv), dojos_path(format: :csv) %></code></li>
2425
</ul>
2526
</div>
2627
</p>
28+
29+
<!-- 年次データフィルタリング -->
30+
<div style="margin: 30px auto; padding: 20px; background: #f8f9fa; border-radius: 8px; max-width: 600px;">
31+
<h3>📊 年次データのフィルタリング</h3>
32+
33+
<% if @selected_year %>
34+
<div style="padding: 10px; background: #d1ecf1; border: 1px solid #bee5eb; border-radius: 4px; margin-bottom: 15px;">
35+
<strong><%= @selected_year %>年末時点</strong>のアクティブな道場を表示中
36+
<%= link_to '全道場を表示', dojos_path, style: 'margin-left: 10px;' %>
37+
</div>
38+
<% end %>
39+
40+
<%= form_with(url: dojos_path, method: :get, local: true, style: 'margin-top: 15px;') do |f| %>
41+
<div style="display: flex; align-items: center; justify-content: center; gap: 10px;">
42+
<%= label_tag :year, '年を選択:', style: 'font-weight: bold;' %>
43+
<%= select_tag :year,
44+
options_for_select(
45+
(2012..Date.current.year).to_a.reverse.map { |y| [y.to_s + '年', y] },
46+
params[:year]
47+
),
48+
include_blank: '全道場',
49+
style: 'padding: 5px; border: 1px solid #ced4da; border-radius: 4px;' %>
50+
51+
<%= button_tag type: 'submit', style: 'padding: 5px 15px; background: #17a2b8; color: white; border: none; border-radius: 4px; cursor: pointer;' do %>
52+
表示
53+
<% end %>
54+
55+
<%= link_to 'CSV', dojos_path(format: :csv, year: params[:year]),
56+
style: 'padding: 5px 15px; background: #28a745; color: white; text-decoration: none; border-radius: 4px;' %>
57+
58+
<%= link_to 'JSON', dojos_path(format: :json, year: params[:year]),
59+
style: 'padding: 5px 15px; background: #6c757d; color: white; text-decoration: none; border-radius: 4px;' %>
60+
</div>
61+
<% end %>
62+
63+
<p style="font-size: smaller; color: #6c757d; margin-top: 15px;">
64+
※ 年を選択すると、その年末時点でアクティブだった道場のデータを表示・ダウンロードできます。
65+
</p>
66+
</div>
2767

2868
<style type="text/css">
2969
/* URL 用のセルにクラスを付けておく想定 */

0 commit comments

Comments
 (0)