#26.Todoリスト作成

# はじめに
今回、Rubyの基本的な構文を学ぶため、一度形として何か作ってみたいということで、Githubのコードを参考にしてTodoリストを作成してみました。
※開発言語に触れることはほぼ皆無なので、全くの初心者レベルを想定していただけると幸いです。

# なぜRuby?
以前に、Goを勉強しているという記事を上げており、今回はRubyとなっているのですが、理由は簡単で仕事で使いそうなのがRubyだったためです。
Goは趣味で少しずつ勉強していく予定という感じで、あと、仕事でも少し使いそうです。
※開発言語はまだ頻繁に使う事はなさそうなのですが念の為勉強していきます。

# とりあえず写経

以下を参考

https://github.com/adrianomonteiroweb/todo-list-ruby


※ちょっとだけ変えているところがあります。

- 操作メニューの項目を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(保存）」と同じらしいです。