10日目のゴールとテーマ
10日目のテーマは「別のアプリに“型”を移植する:タスク管理ミニアプリを作り始める」です。
ここまでで、名簿アプリをかなり育ててきました。
今日はあえてテーマを変えて、
「人」ではなく「タスク(やること)」を扱う
Person クラスの代わりに Task クラスを作る
配列・メニュー・保存の考え方を“そのまま”応用する
という流れで、「学んだことはアプリが変わっても使い回せる」感覚をつかんでもらいます。
なぜあえて“別アプリ”にするのか
「名簿アプリしか作れない人」から抜け出す
同じコードをいじり続けるのも大事ですが、
一度テーマを変えてみると、こういうことに気づきます。
クラスを作る流れは同じ
配列で複数データを持つ流れも同じ
メニューで操作を選ぶ流れも同じ
ファイルに保存・読み込みする流れも同じ
変わるのは「何を扱うか(人なのか、タスクなのか)」だけです。
ここに気づけると、「Rubyでアプリを作る」という感覚が一気に自分のものになります。
今日作るタスク管理ミニアプリのイメージ
まずは機能を日本語で決める
いきなりコードに行かず、先に“仕様”を言葉で決めます。
タスク(やること)を登録できる
登録する項目は「タイトル」「詳細メモ」「締め切り日(任意)」
登録されたタスクを一覧表示できる
「完了したかどうか」を管理できる
完了済みだけ、未完了だけを表示できる
今日はこのうち、
Task クラスを作る
タスクを追加する
タスク一覧を表示する
完了フラグを持たせる
ここまでをしっかり作ります。
締め切り日や保存機能は、11日目以降に育てていくイメージで。
Taskクラスを設計する
「タスクって何を持っている存在か」を言葉にする
タスクは、ざっくり言うとこういう情報を持っています。
タイトル(何をするのか)
メモ(詳細・補足)
完了したかどうか(true / false)
これをそのまま Task クラスに落とし込みます。
最初のTaskクラスを書く
class Task
attr_accessor :title, :memo, :done
def initialize(title, memo, done = false)
@title = title
@memo = memo
@done = done
end
def mark_done
@done = true
end
def mark_undone
@done = false
end
def done_mark
@done ? "[x]" : "[ ]"
end
def summary
"#{done_mark} #{@title}"
end
def detail
text = ""
text += "#{done_mark} タイトル: #{@title}\n"
text += "メモ: #{@memo}\n"
text
end
end
Rubyここで重要なポイントを深掘りします。
attr_accessor :title, :memo, :done
タイトル・メモ・完了フラグを外から読み書きできるようにしています。
Task.new のあとで task.title や task.done = true のように扱えます。
initialize(title, memo, done = false)
タイトルとメモは必須、done はデフォルト false(未完了)にしています。
Task.new(“買い物に行く”, “牛乳と卵”) のように呼べます。
mark_done / mark_undone
完了状態を切り替えるメソッドです。
直接 task.done = true と書いてもいいのですが、
「意味のある名前のメソッド」にしておくと、コードが読みやすくなります。
done_mark
完了状態に応じて “[x]” または “[ ]” を返します。
一覧表示のときに「チェックボックスっぽく」見せるための小技です。
summary / detail
summary は一覧用の1行表示、detail は詳細表示用の複数行テキストです。
Person の introduction と同じように、「表示の責任」を Task に持たせています。
タスクを配列で管理する
tasks配列を用意する
名簿アプリの people と同じように、
タスク管理アプリでは tasks という配列を用意します。
tasks = []
task1 = Task.new("Rubyの勉強", "2週間コースの10日目をやる")
task2 = Task.new("部屋の片付け", "机の上だけでもきれいにする")
tasks << task1
tasks << task2
Rubyこの時点で、tasks は「Task オブジェクトの配列」になっています。
一覧表示してみる
puts "タスク一覧:"
tasks.each_with_index do |task, idx|
puts "#{idx + 1}. #{task.summary}"
end
Ruby例えば、こんな表示になります。
タスク一覧:
1. [ ] Rubyの勉強
2. [ ] 部屋の片付け
ここで感じてほしいのは、
Person のときとまったく同じパターンで書けている
違うのはクラス名とプロパティの中身だけ
ということです。
ユーザー入力からTaskを作る
入力専用メソッドを作る
名簿アプリの build_person_from_input と同じように、
タスク用の入力メソッドを作ります。
def read_non_empty_line(message)
loop do
puts message
input = gets
return "" if input.nil?
text = input.chomp
if text.strip == ""
puts "空では登録できません。何か入力してください。"
else
return text
end
end
end
def build_task_from_input
title = read_non_empty_line("タスクのタイトルを入力してください:")
memo = read_non_empty_line("タスクのメモ(詳細)を入力してください:")
Task.new(title, memo)
end
Rubyここでの重要ポイントは、
名簿アプリで作った read_non_empty_line を“そのまま再利用”していることです。
入力の考え方は、アプリが変わっても同じです。
だからこそ、こういう「汎用的な部品」を作っておく価値があります。
タスク管理用のメニューを作る
まずはメニューの項目を決める
今日の時点では、次のようなメニューにします。
1: タスク一覧を表示
2: 新しいタスクを追加
3: タスクを完了にする
0: 終了
これを show_menu として書きます。
def show_menu
puts "========================"
puts "タスク管理アプリ メニュー"
puts "1: タスク一覧を表示"
puts "2: 新しいタスクを追加"
puts "3: タスクを完了にする"
puts "0: 終了"
puts "番号を入力してください:"
end
Rubyメニュー番号の読み取りは、名簿アプリと同じ read_menu_number を使えます。
def read_menu_number
loop do
input = gets
return 0 if input.nil?
text = input.chomp
if text.match?(/\A[0-9]+\z/)
return text.to_i
else
puts "数字で入力してください。もう一度どうぞ:"
end
end
end
Rubyメインループを書いてみる
タスク管理アプリの中心
ここまでの部品を組み合わせて、メインループを書きます。
tasks = []
loop do
show_menu
choice = read_menu_number
if choice == 0
puts "アプリを終了します。"
break
elsif choice == 1
handle_show_tasks(tasks)
elsif choice == 2
handle_add_task(tasks)
elsif choice == 3
handle_mark_task_done(tasks)
else
puts "不正な番号です。もう一度入力してください。"
end
end
Rubyここでの重要ポイントは、
名簿アプリのメインループとほぼ同じ形になっていることです。
people が tasks に変わり、
handle_show_all が handle_show_tasks に変わっただけです。
メニューごとの処理を書く
1: タスク一覧を表示する
def handle_show_tasks(tasks)
if tasks.empty?
puts "まだタスクが登録されていません。"
return
end
puts "========================"
puts "タスク一覧:"
tasks.each_with_index do |task, idx|
puts "#{idx + 1}. #{task.summary}"
end
end
Rubyここでは、Task#summary を使って1行表示しています。
完了状態も [ ] / [x] で分かるようになっています。
2: 新しいタスクを追加する
def handle_add_task(tasks)
puts "新しいタスクを登録します。"
task = build_task_from_input
tasks << task
puts "タスクを登録しました。"
end
Ruby名簿アプリの handle_add_person とほぼ同じ構造です。
「何を配列に入れているか」だけが違います。
3: タスクを完了にする
ここが今日の“ちょっとだけ考えるポイント”です。
やりたいことはこうです。
タスク一覧を番号付きで表示する
「どのタスクを完了にするか」の番号を入力してもらう
そのタスクの done を true にする
コードにしていきます。
def handle_mark_task_done(tasks)
if tasks.empty?
puts "まだタスクが登録されていません。"
return
end
puts "完了にしたいタスクの番号を選んでください。"
tasks.each_with_index do |task, idx|
puts "#{idx + 1}. #{task.summary}"
end
print "番号:"
number_text = gets&.chomp.to_s
unless number_text.match?(/\A[0-9]+\z/)
puts "数字で入力してください。"
return
end
index = number_text.to_i - 1
if index < 0 || index >= tasks.length
puts "その番号のタスクは存在しません。"
return
end
task = tasks[index]
task.mark_done
puts "タスクを完了にしました:#{task.summary}"
end
Rubyここで深掘りしたいポイントは三つあります。
一つ目は、「一覧表示と同じ順番で番号を振っている」ことです。
each_with_index で 1 から番号を振り、
ユーザーにはその番号を入力してもらいます。
二つ目は、「入力チェックをちゃんとしている」ことです。
数字以外が入ったら弾き、
範囲外の番号(0 や tasks.length+1 など)も弾いています。
これで、変な入力でアプリが壊れにくくなります。
三つ目は、「完了状態の変更を Task に任せている」ことです。
task.done = true と直接書くのではなく、
task.mark_done を呼んでいます。
これにより、「完了にする」という意味がコードから読み取れます。
10日目で一番大事な気づき
「やっていることは名簿アプリと同じ」だと分かるかどうか
ここまで書いてきて、
名簿アプリとタスク管理アプリの共通点が見えてきたはずです。
クラスを作る(Person → Task)
配列で複数データを持つ(people → tasks)
メニューで操作を選ぶ
入力用メソッドを作る
一覧表示用メソッドを作る
状態を変更するメソッドを作る(mark_done など)
つまり、「アプリのテーマ」が変わっても、
考え方とパターンはほとんど同じです。
ここに気づけたら、もう「名簿アプリ職人」ではなく、
「Rubyで小さなアプリを設計できる人」の入り口に立っています。
10日目のまとめ
今日のポイントを短く整理します。
タスク管理という新しいテーマを選び、
Task クラスを自分で設計した。
Task は title・memo・done を持ち、
summary や detail で「表示の仕方」も自分で知っている。
tasks 配列で複数タスクを管理し、
メニュー+メインループで操作を選べるようにした。
タスクを完了にする処理では、
一覧表示 → 番号入力 → 入力チェック → mark_done という流れを自分で組み立てた。
そして何より、名簿アプリで学んだパターンが
そのままタスク管理アプリに応用できることを体感した。
次のステップでは、このタスク管理アプリにも
ファイル保存・読み込みを足したり、
締め切り日や優先度を持たせたりして、
「自分が本当に使いたいツール」に近づけていくことができます。
ここで一度、自分にこう聞いてみてほしいです。
「もし自分専用のタスクアプリを作るなら、どんな機能が欲しい?」
その答えが、11日目以降の設計の種になります。
