【Ruby】自分しか使わないタスク管理アプリをRubyだけで作ってみた

どうもこんにちは。

今回は、Rubyの勉強がてら、ターミナルで使用するタスク管理アプリをRubyだけで作ってみました。

:::note warn
RailsのようにHTMLを使用してUIを作成するわけではないです。
ターミナルで使用する簡素なタスク管理アプリです。
:::

# 前提

Rubyがインストールされていることを前提に話を進めます。

# 手順

## 1. 作業ディレクトリ準備

```sh
mkdir only_ruby_task_app && cd only_ruby_task_app
```

## 2. rubyファイル生成

```sh
touch app.rb
```

## 3. コード記述

今回は、エディタ使いません。ターミナルで完結させます。

```sh
vi app.rb
```

以下をコピペします。

```rb:app.rb
require 'json'
require 'colorize'

# タスクデータを定義するクラス
class Task
  attr_accessor :id, :title, :completed

  def initialize(id, title, completed = false)
    @id = id
    @title = title
    @completed = completed
  end

  def to_hash
    {
      id: @id,
      title: @title,
      completed: @completed
    }
  end
end

# タスク管理クラス
class TaskManager
  DATA_FILE = 'tasks.json'

  def initialize
    @tasks = load_tasks
  end

  def add_task(title)
    id = next_id
    task = Task.new(id, title)
    @tasks << task
    save_tasks
    puts "タスク「#{title}」を追加しました。ID: #{id}"
  end

  def list_tasks
    if @tasks.empty?
      puts "タスクはありません。"
    else
      puts "タスク一覧:"
      @tasks.each do |task|
        status = task.completed ? "[完了]" : "[未完了]"
        puts "#{task.id}. #{status} #{task.title}"
      end
    end
  end

  def complete_task(id)
    task = find_task(id)
    if task
      task.completed = true
      save_tasks
      puts "タスク「#{task.title}」を完了にしました。"
    else
      puts "ID #{id} のタスクが見つかりません。"
    end
  end

  def delete_task(id)
    task = find_task(id)
    if task
      @tasks.delete(task)
      save_tasks
      puts "タスク「#{task.title}」を削除しました。"
    else
      puts "ID #{id} のタスクが見つかりません。"
    end
  end

  private

  def load_tasks
    if File.exist?(DATA_FILE)
      data = JSON.parse(File.read(DATA_FILE))
      data.map { |t| Task.new(t['id'], t['title'], t['completed']) }
    else
      []
    end
  end

  def save_tasks
    data = @tasks.map(&:to_hash)
    File.open(DATA_FILE, 'w') do |f|
      f.write(JSON.pretty_generate(data))
    end
  end

  def next_id
    if @tasks.empty?
      1
    else
      @tasks.map(&:id).max + 1
    end
  end

  def find_task(id)
    @tasks.find { |task| task.id == id }
  end
end

def display_menu
  puts "\nタスク管理アプリ"
  puts "1. タスクを追加"
  puts "2. タスクを一覧表示"
  puts "3. タスクを完了"
  puts "4. タスクを削除"
  puts "5. アプリを終了"
  print "選択してください（1-5）："
end

def main
  manager = TaskManager.new

  loop do
    display_menu
    choice = gets.chomp

    case choice
    when '1'
      print "タスクのタイトルを入力してください: "
      title = gets.chomp
      if title.strip.empty?
        puts "タイトルは空にできません。"
      else
        manager.add_task(title)
      end
    when '2'
      manager.list_tasks
    when '3'
      print "完了にするタスクのIDを入力してください: "
      id = gets.chomp.to_i
      manager.complete_task(id)
    when '4'
      print "削除するタスクのIDを入力してください: "
      id = gets.chomp.to_i
      manager.delete_task(id)
    when '5'
      puts "アプリを終了します。"
      break
    else
      puts "無効な選択です。1から5の数字を入力してください。"
    end
  end
end

# アプリケーションの実行
main
```

## 4. 起動！

```sh
ruby app.rb
```

こんな感じで表示されればOK！

![スクリーンショット 2024-11-03 10.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/d8dfe4b0-1a5b-1756-6aec-44e6705f9578.png)

でも白黒で読みづらい...

よし、文字に色をつけよう！

## 5. 色をつけるためのGemをインストール

```sh
gem install colorize
```

## 6. app.rbでrequire

```rb
# ファイルの上の方に記述
require 'colorize'
```

## 7. 出力する文字列に色を指定

```rb
# display_menuメソッドに出力する文字列あります！

def display_menu
  puts "\nタスク管理アプリ".cyan
  puts "1. タスクを追加".green
  puts "2. タスクを一覧表示".green
  puts "3. タスクを完了".green
  puts "4. タスクを削除".green
  puts "5. アプリを終了".red
  print "選択してください（1-5）：".yellow
end
```

## 8. いざ実行！

![スクリーンショット 2024-11-03 11.00.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/5e01c614-3c91-8205-6e38-655590eeadc5.png)

いい感じ！

追加したタスクは、データベースじゃなくてJSONファイルで管理するようにしています。
原始的ですが、単純明快で使いやすいです。

以上