はじめに
今回、Rubyの基本的な構文を学ぶため、一度形として何か作ってみたいということで、Githubのコードを参考にしてTodoリストを作成してみました。
※開発言語に触れることはほぼ皆無なので、全くの初心者レベルを想定していただけると幸いです。
なぜRuby?
以前に、Goを勉強しているという記事を上げており、今回はRubyとなっているのですが、理由は簡単で仕事で使いそうなのがRubyだったためです。
Goは趣味で少しずつ勉強していく予定という感じで、あと、仕事でも少し使いそうです。
※開発言語はまだ頻繁に使う事はなさそうなのですが念の為勉強していきます。
とりあえず写経
以下を参考
※ちょっとだけ変えているところがあります。
- 操作メニューの項目を6個に増やす
- 操作項目以外の番号を入れた際にメッセージと共に操作メニューに戻す
- 各タスク内容を変更できるようにする
- タスクリストからidを消した際、idが降順に振り直される
- リストを削除する際に全削除ができるようにする
app.rb
require_relative 'task'
require_relative 'task_manager'
require_relative 'data_store'
manager = TaskManager.new
manager.loading_tasks
loop do
puts "操作を選択してね〜:"
puts "1. タスク新規追加"
puts "2. タスクリスト"
puts "3. タスク完了"
puts "4. タスク削除"
puts "5. タスク変更"
puts "6. 終了"
print "番号を入力してください: "
input = gets.chomp.to_i
if input.to_s =~ /^[1-6]$/
option = input
end
case option
when 1
print "タイトル: "
title = gets.chomp
print "コメント: "
description = gets.chomp
task = manager.add_task(title, description)
puts "タスク追加しました: #{task}"
when 2
puts "タスクリスト:"
manager.list_tasks.each{ |task| puts task }
when 3
print "完了済みタスクのIDは?: "
id = gets.chomp.to_i
manager.define_success(id)
puts "完了済みにしました"
when 4
print "削除するタスクのIDは?(すべて削除したい場合は 'all' と入力): "
input = gets.chomp
if input == "all"
manager.remove_all_tasks
puts "すべて削除しました"
elsif input != "all"
id = input.to_i
manager.remove_task(id)
puts "タスクID #{id} を削除しました"
else
puts "無効な入力です。数値または 'all' を入力してください"
end
when 5
print "変更したいタスクのIDは?"
id = gets.chomp.to_i
print "変更内容は?"
input = gets.chomp
if input =~ /^\d+$/
change_description = input.to_i
else
change_description = input
end
manager.change_comment(id, change_description)
when 6
manager.salve_tasks
puts "終了中..."
#処理がら抜ける
sleep(1)
break
else
puts "無効な入力です。操作に戻ります。"
sleep(1)
end
end
task_manager.rb
class TaskManager
def initialize
@tasks = []
@next_id = 1
end
def add_task(title, description)
task = Task.new(@next_id, title, description)
@tasks << task
@next_id += 1
task
end
def list_tasks
@tasks
end
def define_success(id)
task = @tasks.find { |t| t.id == id }
task.define_success if task
end
def remove_all_tasks
@tasks.clear
@next_id = 1
end
def remove_task(id)
@tasks.reject! { |t| t.id == id }
@tasks.each_with_index do |task, index|
task.id = index + 1
end
@next_id = @tasks.size + 1
end
def salve_tasks
DataStore.salve(@tasks)
end
def change_comment(id, change_description )
task = @tasks.find{|t| t.id == id}
if task
task.description = change_description
else
puts "タスクが見つかりませんでした。"
end
end
def loading_tasks
@tasks = DataStore.loading
@next_id = @tasks.empty? ? 1 : @tasks.max_by(&:id).id + 1
end
end
task.rb
class Task
attr_accessor :id, :title, :description, :success, :created_date, :succes_date
def initialize(id, title, description )
@id = id
@title = title
@description = description
@success = false
@created_date = Time.now
@succes_date = nil
end
def define_success
@success = true
@succes_date = Time.now
end
def to_s
status = @success ? "Success" : "Pending"
"ID #{@id} | Title: #{@title} | Description: #{@description} | Status: #{status} | Created at: #{@created_date} | Successed at: #{@succes_date}"
end
def to_h
{
id: @id,
title: @title,
description: @description,
success: @success,
created_date: @created_date,
succes_date: @succes_date
}
end
end
data_store.rb
require 'json'
require 'time'
class DataStore
FILE_NAME = 'tasks.json'
def self.salve(tasks)
File.write(FILE_NAME, JSON.pretty_generate(tasks.map(&:to_h)))
end
def self.loading
return [] unless File.exist?(FILE_NAME)
JSON.parse(File.read(FILE_NAME)).map do |task_hash|
Task.new(task_hash["id"], task_hash["title"], task_hash["description"]).tap do |tarefa|
tarefa.success = task_hash["success"]
tarefa.created_date = Time.parse(task_hash["created_date"])
tarefa.succes_date = task_hash["succes_date"] ? Time.parse(task_hash["succes_date"]) : nil
end
end
end
end
tasks.json(タスク追加前)
{}
※タスクを追加したらファイルに書き込みされていくイメージ
実行してみる
※見づらいため改行を入れています。実際の動作だと改行は入っておりません。
% ruby app.rb
操作を選択してね〜:
1. タスク新規追加
2. タスクリスト
3. タスク完了
4. タスク削除
5. タスク変更
6. 終了
番号を入力してください: 1
タイトル: test
コメント: 練習用
タスク追加しました: ID 1 | Title: test | Description: 練習用 | Status: Pending | Created at: 2025-04-19 19:55:39 +0900 | Successed at:
操作を選択してね〜:
1. タスク新規追加
2. タスクリスト
3. タスク完了
4. タスク削除
5. タスク変更
6. 終了
番号を入力してください: 2
タスクリスト:
ID 1 | Title: test | Description: 練習用 | Status: Pending | Created at: 2025-04-19 19:55:39 +0900 | Successed at:
操作を選択してね〜:
1. タスク新規追加
2. タスクリスト
3. タスク完了
4. タスク削除
5. タスク変更
6. 終了
番号を入力してください: 6
終了中...
%
tasks.json(タスク追加後)
[
{
"id": 1,
"title": "test",
"description": "練習用",
"success": false,
"created_date": "2025-04-19 19:55:39 +0900",
"succes_date": null
}
]
追加されてますね👏
まとめ
結構知り合いの方であったり、動画などでおっしゃっている方が多かったのですが、
実際に形として何かを作ってから、本や動画などで勉強すると良いとのことで、実際やってみると理解度が深まるなと実感しました。まだ、完全に理解しきれてるわけではないので、今後もこのやり方で勉強を進めていきたいと思います。
あと、勉強して思ったことなのですが、エンジニア歴が長く、AIや本での情報収集が普及されていない時代からこんな難しいことやってる方々は凄いなと思いました。
※関係ないのですが、「tarefa」っていう変数名何かな?と思って調べたら、ポルトガル語らしく、英語の「task(任務、仕事)」と同じ意味らしいですね。
「salve」は「save(保存)」と同じらしいです。