Skip to content

Commit 3c24c7b

Browse files
committed
feat: Dojoモデルに inactivated_at カラムを追加
- データベースに inactivated_at カラムを追加(datetime型、インデックス付き) - note カラムを string から text 型に変更(再活性化履歴の記録用) - is_active と inactivated_at の同期処理を実装 - active_at スコープを追加(特定時点でのアクティブ道場を取得) - 基本的なモデルテストを追加 注意: db/dojos.yaml がマスターデータのため、 実際の inactivated_at の永続化にはYAMLファイルの更新が必要 (次のステップで実装予定) refs #1373
1 parent fdd31df commit 3c24c7b

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

app/models/dojo.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class Dojo < ApplicationRecord
1616
scope :default_order, -> { order(prefecture_id: :asc, order: :asc) }
1717
scope :active, -> { where(is_active: true ) }
1818
scope :inactive, -> { where(is_active: false) }
19+
20+
# 新しいスコープ: 特定の日時点でアクティブだったDojoを取得
21+
scope :active_at, ->(date) {
22+
where('created_at <= ?', date)
23+
.where('inactivated_at IS NULL OR inactivated_at > ?', date)
24+
}
1925

2026
validates :name, presence: true, length: { maximum: 50 }
2127
validates :email, presence: false
@@ -74,8 +80,50 @@ def annual_count(period)
7480
]
7581
end
7682
end
83+
84+
# インスタンスメソッド
85+
def active?
86+
inactivated_at.nil?
87+
end
88+
89+
def active_at?(date)
90+
created_at <= date && (inactivated_at.nil? || inactivated_at > date)
91+
end
92+
93+
# 再活性化メソッド
94+
def reactivate!
95+
if inactivated_at.present?
96+
# 非活動期間を note に記録
97+
inactive_period = "#{inactivated_at.strftime('%Y-%m-%d')}#{Date.today}"
98+
99+
if note.present?
100+
self.note += "\n非活動期間: #{inactive_period}"
101+
else
102+
self.note = "非活動期間: #{inactive_period}"
103+
end
104+
end
105+
106+
update!(
107+
is_active: true,
108+
inactivated_at: nil
109+
)
110+
end
111+
112+
# is_activeとinactivated_atの同期(移行期間中)
113+
before_save :sync_active_status
77114

78115
private
116+
117+
def sync_active_status
118+
if is_active_changed?
119+
if is_active == false && inactivated_at.nil?
120+
self.inactivated_at = Time.current
121+
elsif is_active == true && inactivated_at.present?
122+
# is_activeがtrueに変更された場合、inactivated_atをnilに
123+
self.inactivated_at = nil
124+
end
125+
end
126+
end
79127

80128
# Now 6+ tags are available since this PR:
81129
# https://github.com/coderdojo-japan/coderdojo.jp/pull/1697
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class AddInactivatedAtToDojos < ActiveRecord::Migration[8.0]
2+
def change
3+
add_column :dojos, :inactivated_at, :datetime, default: nil
4+
add_index :dojos, :inactivated_at
5+
end
6+
end
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class ChangeNoteToTextInDojos < ActiveRecord::Migration[8.0]
2+
def up
3+
change_column :dojos, :note, :text, null: false, default: ""
4+
end
5+
6+
def down
7+
# 255文字を超えるデータがある場合は警告
8+
long_notes = Dojo.where("LENGTH(note) > 255").pluck(:id, :name)
9+
if long_notes.any?
10+
raise ActiveRecord::IrreversibleMigration,
11+
"Cannot revert: These dojos have notes longer than 255 chars: #{long_notes}"
12+
end
13+
14+
change_column :dojos, :note, :string, null: false, default: ""
15+
end
16+
end

spec/models/dojo_spec.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,48 @@
8585
expect(missing_ids).to match_array(allowed_missing_ids)
8686
end
8787
end
88+
89+
# inactivated_at カラムの基本的なテスト
90+
describe 'inactivated_at functionality' do
91+
before do
92+
@dojo = Dojo.create!(
93+
name: "CoderDojo テスト",
94+
95+
order: 0,
96+
description: "テスト用Dojo",
97+
logo: "https://example.com/logo.png",
98+
url: "https://test.coderdojo.jp",
99+
tags: ["Scratch"],
100+
prefecture_id: 13
101+
)
102+
end
103+
104+
describe '#sync_active_status' do
105+
it 'sets inactivated_at when is_active becomes false' do
106+
expect(@dojo.inactivated_at).to be_nil
107+
@dojo.update!(is_active: false)
108+
expect(@dojo.inactivated_at).to be_present
109+
end
110+
111+
it 'clears inactivated_at when is_active becomes true' do
112+
@dojo.update!(is_active: false)
113+
expect(@dojo.inactivated_at).to be_present
114+
115+
@dojo.update!(is_active: true)
116+
expect(@dojo.inactivated_at).to be_nil
117+
end
118+
end
119+
120+
describe '#active?' do
121+
it 'returns true when inactivated_at is nil' do
122+
@dojo.inactivated_at = nil
123+
expect(@dojo.active?).to be true
124+
end
125+
126+
it 'returns false when inactivated_at is present' do
127+
@dojo.inactivated_at = Time.current
128+
expect(@dojo.active?).to be false
129+
end
130+
end
131+
end
88132
end

0 commit comments

Comments
 (0)