1
+ require 'fileutils'
2
+
1
3
namespace :dojos do
2
4
desc 'Git履歴からinactivated_at日付を抽出してYAMLファイルに反映(引数でDojo IDを指定可能)'
3
5
task :extract_inactivated_at_from_git , [ :dojo_id ] => :environment do |t , args |
@@ -21,7 +23,9 @@ namespace :dojos do
21
23
22
24
puts ""
23
25
updated_count = 0
26
+ updates_to_apply = [ ] # 更新情報を保存する配列
24
27
28
+ # Phase 1: 全てのDojoの情報を収集(YAMLを変更せずに)
25
29
target_dojos . each do |dojo |
26
30
puts "処理中: #{ dojo . name } (ID: #{ dojo . id } )"
27
31
@@ -40,11 +44,22 @@ namespace :dojos do
40
44
# 該当Dojoブロック内で is_active: false を見つける
41
45
if in_dojo_block && line . match? ( /^\s *is_active: false/ )
42
46
target_line_number = index + 1 # git blameは1-indexedなので+1
47
+ # デバッグ: 重要なDojoの行番号を確認
48
+ if [ 203 , 201 , 125 , 222 , 25 , 20 ] . include? ( dojo . id )
49
+ puts " [DEBUG] ID #{ dojo . id } : is_active:false は #{ target_line_number } 行目"
50
+ end
43
51
break
44
52
end
45
53
end
46
54
47
55
if target_line_number
56
+ # ファイルの行数チェック
57
+ total_lines = yaml_lines . length
58
+ if target_line_number > total_lines
59
+ puts " ✗ エラー: 行番号 #{ target_line_number } が範囲外です(ファイル行数: #{ total_lines } )"
60
+ next
61
+ end
62
+
48
63
# git blame を使って該当行の最新コミット情報を取得
49
64
# --porcelain で解析しやすい形式で出力
50
65
blame_cmd = "git blame #{ yaml_path } -L #{ target_line_number } ,+1 --porcelain 2>&1"
@@ -76,40 +91,17 @@ namespace :dojos do
76
91
next
77
92
end
78
93
79
- # YAMLファイルのDojoブロックを見つけて更新
80
- yaml_updated = false
81
- yaml_lines . each_with_index do |line , index |
82
- if line . match? ( /^- id: #{ dojo . id } $/ )
83
- # 該当Dojoブロックの最後に inactivated_at を追加
84
- insert_index = index + 1
85
- while insert_index < yaml_lines . length && !yaml_lines [ insert_index ] . match? ( /^- id:/ )
86
- # is_active: false の次の行に挿入したい
87
- if yaml_lines [ insert_index - 1 ] . match? ( /is_active: false/ )
88
- # 既に inactivated_at がある場合はスキップ(冪等性)
89
- if yaml_lines [ insert_index ] . match? ( /^\s *inactivated_at:/ )
90
- puts " - inactivated_at は既に設定されています"
91
- yaml_updated = false
92
- break
93
- end
94
-
95
- yaml_lines . insert ( insert_index ,
96
- " inactivated_at: '#{ inactivated_date . strftime ( '%Y-%m-%d %H:%M:%S' ) } '\n " )
97
- yaml_updated = true
98
- break
99
- end
100
- insert_index += 1
101
- end
102
- break
103
- end
104
- end
94
+ # 更新情報を保存(実際の更新は後で一括実行)
95
+ updates_to_apply << {
96
+ dojo_id : dojo . id ,
97
+ dojo_name : dojo . name ,
98
+ date : inactivated_date ,
99
+ commit_id : commit_id ,
100
+ author_name : author_name
101
+ }
105
102
106
- if yaml_updated
107
- updated_count += 1
108
- puts " ✓ inactivated_at を追加: #{ inactivated_date . strftime ( '%Y-%m-%d %H:%M:%S' ) } "
109
- puts " コミット: #{ commit_id [ 0 ..7 ] } by #{ author_name } "
110
- elsif !args [ :dojo_id ]
111
- puts " - スキップ(既に設定済みまたは更新失敗)"
112
- end
103
+ puts " ✓ inactivated_at の日付を取得: #{ inactivated_date . strftime ( '%Y-%m-%d %H:%M:%S' ) } "
104
+ puts " コミット: #{ commit_id [ 0 ..7 ] } by #{ author_name } "
113
105
else
114
106
puts " ✗ コミット情報の取得に失敗"
115
107
end
@@ -120,17 +112,74 @@ namespace :dojos do
120
112
puts ""
121
113
end
122
114
115
+ # Phase 2: 収集した情報を元にYAMLファイルを一括更新
116
+ if !args [ :dojo_id ] && updates_to_apply . any?
117
+ puts "\n === Phase 2: YAMLファイルを更新 ==="
118
+ puts "#{ updates_to_apply . count } 個のDojoを更新します\n \n "
119
+
120
+ # 更新情報を日付順(ID順)にソート
121
+ updates_to_apply . sort_by! { |u | u [ :dojo_id ] }
122
+
123
+ updates_to_apply . each do |update |
124
+ puts "更新中: #{ update [ :dojo_name ] } (ID: #{ update [ :dojo_id ] } )"
125
+
126
+ # YAMLファイルのDojoブロックを見つけて更新
127
+ yaml_lines . each_with_index do |line , index |
128
+ if line . match? ( /^- id: #{ update [ :dojo_id ] } $/ )
129
+ # 該当Dojoブロックの最後に inactivated_at を追加
130
+ insert_index = index + 1
131
+ while insert_index < yaml_lines . length && !yaml_lines [ insert_index ] . match? ( /^- id:/ )
132
+ # is_active: false の次の行に挿入したい
133
+ if yaml_lines [ insert_index - 1 ] . match? ( /is_active: false/ )
134
+ # 既に inactivated_at がある場合はスキップ(冪等性)
135
+ if yaml_lines [ insert_index ] . match? ( /^\s *inactivated_at:/ )
136
+ puts " - inactivated_at は既に設定されています"
137
+ break
138
+ end
139
+
140
+ yaml_lines . insert ( insert_index ,
141
+ " inactivated_at: '#{ update [ :date ] . strftime ( '%Y-%m-%d %H:%M:%S' ) } '\n " )
142
+ updated_count += 1
143
+ puts " ✓ inactivated_at を追加: #{ update [ :date ] . strftime ( '%Y-%m-%d %H:%M:%S' ) } "
144
+ break
145
+ end
146
+ insert_index += 1
147
+ end
148
+ break
149
+ end
150
+ end
151
+ end
152
+ end
153
+
123
154
# 全Dojoモードで更新があった場合のみYAMLファイルを書き戻す
124
155
if !args [ :dojo_id ] && updated_count > 0
125
- File . write ( yaml_path , yaml_lines . join )
126
-
127
- puts "=== 完了 ==="
128
- puts "合計 #{ updated_count } 個のDojoに inactivated_at を追加しました"
129
- puts ""
130
- puts "次のステップ:"
131
- puts "1. db/dojos.yaml の変更内容を確認"
132
- puts "2. rails dojos:update_db_by_yaml を実行してDBに反映"
133
- puts "3. 変更をコミット"
156
+ begin
157
+ # バックアップを作成(tmpディレクトリに)
158
+ backup_path = Rails . root . join ( 'tmp' , "dojos.yaml.backup.#{ Time . now . strftime ( '%Y%m%d_%H%M%S' ) } " )
159
+ FileUtils . cp ( yaml_path , backup_path )
160
+ puts "\n 📦 バックアップ作成: #{ backup_path } "
161
+
162
+ # YAMLファイルを更新
163
+ File . write ( yaml_path , yaml_lines . join )
164
+
165
+ # YAML構文チェック(DateとTimeクラスを許可)
166
+ YAML . load_file ( yaml_path , permitted_classes : [ Date , Time ] )
167
+
168
+ puts "\n === 完了 ==="
169
+ puts "合計 #{ updated_count } 個のDojoに inactivated_at を追加しました"
170
+ puts ""
171
+ puts "次のステップ:"
172
+ puts "1. db/dojos.yaml の変更内容を確認"
173
+ puts "2. rails dojos:update_db_by_yaml を実行してDBに反映"
174
+ puts "3. 変更をコミット"
175
+ rescue => e
176
+ puts "\n ❌ エラー: YAMLファイルの更新に失敗しました"
177
+ puts " #{ e . message } "
178
+ puts "\n 🔙 バックアップから復元中..."
179
+ FileUtils . cp ( backup_path , yaml_path ) if File . exist? ( backup_path )
180
+ puts " 復元完了"
181
+ raise e
182
+ end
134
183
elsif !args [ :dojo_id ]
135
184
puts "=== 完了 ==="
136
185
puts "更新対象のDojoはありませんでした(または既に設定済み)"
0 commit comments