Skip to content

Commit 658583f

Browse files
committed
docs: 実装計画を大幅に簡素化 - 既存動作の正しい理解に基づく
重要な気づき: - 既存の/dojosは既に全道場(非アクティブ含む)を返している - CSV形式のサポートを追加するだけで良い - render_yearly_statsなどの複雑なメソッドは不要 - yearパラメータでのフィルタリングのみ追加 これにより実装がシンプルになり、既存コードの変更を最小限に
1 parent c3a24db commit 658583f

File tree

1 file changed

+10
-96
lines changed

1 file changed

+10
-96
lines changed

docs/plan_download_yearly_stats.md

Lines changed: 10 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ CoderDojoの統計データを年次でダウンロードできる機能を実
55

66
### データの取得範囲
77
- **yearパラメータなし(デフォルト)**:
8-
- HTML表示: 現在アクティブな道場のみ(既存の動作を維持)
9-
- CSV/JSONダウンロード: 全道場(アクティブ + 非アクティブ)
8+
- 全形式(HTML/JSON/CSV): 全道場(アクティブ + 非アクティブ)※既存の動作そのまま
109
- **yearパラメータあり(例: year=2024)**:
1110
- HTML/JSON/CSV すべての形式: その年末時点でアクティブだった道場のみ
1211

@@ -88,19 +87,9 @@ class DojosController < ApplicationController
8887

8988
@page_title = "#{@selected_year}年末時点のCoderDojo一覧"
9089
else
91-
# yearパラメータなしの場合
92-
# HTML表示: 現在のアクティブな道場のみ(既存の実装を維持)
93-
# CSV/JSONダウンロード: 全道場(アクティブ + 非アクティブ)
94-
if request.format.html?
95-
# HTMLの場合は現在アクティブな道場のみ
96-
dojos_scope = Dojo.active
97-
else
98-
# CSV/JSONの場合は全道場(非アクティブも含む)
99-
dojos_scope = Dojo.all
100-
end
101-
90+
# yearパラメータなしの場合(既存の実装そのまま)
10291
@dojos = []
103-
dojos_scope.includes(:prefecture).order(order: :asc).each do |dojo|
92+
Dojo.includes(:prefecture).order(order: :asc).all.each do |dojo|
10493
@dojos << {
10594
id: dojo.id,
10695
url: dojo.url,
@@ -120,88 +109,13 @@ class DojosController < ApplicationController
120109
respond_to do |format|
121110
format.html { render :index } # => app/views/dojos/index.html.erb
122111
format.json { render json: @dojos }
123-
format.csv { send_data render_to_string, type: :csv }
112+
format.csv { send_data render_to_string, type: :csv } # 新規追加
124113
end
125114
end
126115

127116
def show
128117
# 既存の実装のまま
129118
end
130-
131-
private
132-
133-
def render_yearly_stats
134-
@period_start = 2012
135-
@period_end = Date.current.year
136-
137-
# yearパラメータが指定されている場合(整数のみ許可)
138-
if @selected_year # 既にindexアクションで設定済み
139-
period = Time.zone.local(@selected_year).beginning_of_year..Time.zone.local(@selected_year).end_of_year
140-
@stat = Stat.new(period)
141-
@yearly_data = prepare_single_year_data(@stat, @selected_year)
142-
filename_suffix = @selected_year.to_s
143-
else
144-
# yearパラメータなし = 全年次データ
145-
period = Time.zone.local(@period_start).beginning_of_year..Time.zone.local(@period_end).end_of_year
146-
@stat = Stat.new(period)
147-
@yearly_data = prepare_all_years_data(@stat)
148-
filename_suffix = 'all'
149-
end
150-
151-
# CSVまたはJSONとして返す
152-
respond_to do |format|
153-
format.csv do
154-
send_data render_to_string(template: 'dojos/yearly_stats'),
155-
type: :csv,
156-
filename: "coderdojo_stats_#{filename_suffix}_#{Date.current.strftime('%Y%m%d')}.csv"
157-
end
158-
format.json { render json: @yearly_data }
159-
end
160-
end
161-
162-
def prepare_all_years_data(stat)
163-
active_dojos = stat.annual_dojos_with_historical_data
164-
new_dojos = stat.annual_new_dojos_count
165-
166-
# 年ごとのデータを整形
167-
years = (@period_start..@period_end).map(&:to_s)
168-
years.map do |year|
169-
prev_year = (year.to_i - 1).to_s
170-
{
171-
year: year,
172-
active_dojos_at_year_end: active_dojos[year] || 0,
173-
new_dojos: new_dojos[year] || 0,
174-
inactivated_dojos: calculate_inactivated_count(year),
175-
cumulative_total: active_dojos[year] || 0,
176-
net_change: prev_year && active_dojos[prev_year] ?
177-
(active_dojos[year] || 0) - active_dojos[prev_year] :
178-
(active_dojos[year] || 0)
179-
}
180-
end
181-
end
182-
183-
def prepare_single_year_data(stat, year)
184-
# 特定年のアクティブな道場リストを返す
185-
end_of_year = Time.zone.local(year).end_of_year
186-
dojos = Dojo.active_at(end_of_year).includes(:prefecture)
187-
188-
dojos.map do |dojo|
189-
{
190-
id: dojo.id,
191-
name: dojo.name,
192-
prefecture: dojo.prefecture.name,
193-
url: dojo.url,
194-
created_at: dojo.created_at.strftime('%Y-%m-%d'),
195-
is_active_at_year_end: dojo.active_at?(end_of_year)
196-
}
197-
end
198-
end
199-
200-
def calculate_inactivated_count(year)
201-
start_of_year = Time.zone.local(year.to_i).beginning_of_year
202-
end_of_year = Time.zone.local(year.to_i).end_of_year
203-
Dojo.where(inactivated_at: start_of_year..end_of_year).sum(:counter)
204-
end
205119
end
206120
```
207121

@@ -382,10 +296,15 @@ RSpec.describe DojosController, type: :controller do
382296
expect(csv[0]).to eq(['', '年末アクティブ道場数', '新規開設数', '非アクティブ化数', '累積合計', '純増減'])
383297
end
384298

385-
it 'yearパラメータなしの場合は非アクティブな道場も含む(CSV/JSON' do
299+
it 'yearパラメータなしの場合は非アクティブな道場も含む(全形式' do
386300
active_dojo = create(:dojo, is_active: true)
387301
inactive_dojo = create(:dojo, is_active: false, inactivated_at: '2021-03-01')
388302

303+
# HTML形式: 全道場を含む
304+
get :index, format: :html
305+
expect(assigns(:dojos).map { |d| d[:id] }).to include(active_dojo.id)
306+
expect(assigns(:dojos).map { |d| d[:id] }).to include(inactive_dojo.id)
307+
389308
# JSON形式: 全道場を含む
390309
get :index, format: :json
391310
json_response = JSON.parse(response.body)
@@ -399,11 +318,6 @@ RSpec.describe DojosController, type: :controller do
399318
csv_ids = csv.map { |row| row['ID'].to_i }
400319
expect(csv_ids).to include(active_dojo.id)
401320
expect(csv_ids).to include(inactive_dojo.id)
402-
403-
# HTML形式: アクティブな道場のみ(既存の動作を維持)
404-
get :index, format: :html
405-
expect(assigns(:dojos).map { |d| d[:id] }).to include(active_dojo.id)
406-
expect(assigns(:dojos).map { |d| d[:id] }).not_to include(inactive_dojo.id)
407321
end
408322
end
409323

0 commit comments

Comments
 (0)