スポンサーリンク

プロを目指す人のためのRuby入門[改訂2版]を写経してみる(3)第8章 モジュールを理解する

スポンサードリンク

プロを目指す人のためのRuby入門[改訂2版]を写経してみる 目次

  1. (1)第2章 FizzBuzzプログラム
  2. (2)第7章 クラスの作成を理解する
  3. (3)第8章 モジュールを理解する

開発環境

Windows 10 Pro 21H1
Hyper-Vを有効化
VisualStudioCode (wsl用の拡張機能インストール済み)

WSL2 Ubuntu 20.04 LTS
rbenv 1.2.0-8-ga76c4aa
ruby 3.1
nvm 0.39.1
node 16.13.2
yarn 1.22.17
sqlite3
google-chrome-stable

test/raibowable_test.rb

test/raibowable_test.rb

require 'minitest/autorun'
require_relative '../lib/rainbowable'

class RainbowableTest < Minitest::Test
  def setup
    # 文字列や配列でrainbowメソッドが呼び出せるよう、Rainbowableモジュールをinclude
    String.include Rainbowable
    Array.include Rainbowable
  end

  def test_rainbow
    expected = "\e[31mH\e[32me\e[33ml\e[34ml\e[35mo\e[36m,\e[31m \e[32mw\e[33mo\e[34mr\e[35ml\e[36md\e[31m!\e[0m"
    assert_equal expected, 'Hello, world!'.rainbow

    expected = "\e[31m[\e[32m1\e[33m,\e[34m \e[35m2\e[36m,\e[31m \e[32m3\e[33m]\e[0m"
    assert_equal expected, [1, 2, 3].rainbow

    # rainbowメソッドの戻り値をターミナルに出力
    puts 'Hello, world!'.rainbow
    puts [1,2,3].rainbow
  end
end

lib/raibowable.rb

module Rainbowable
  def rainbow
    #1.to_sメソッドを使って自分自身の文字列表現を取得する
    str = self.to_s

    # ループカウンタと、色を付けた文字を順に格納する配列を用意
    count = 0
    colored_chars = []
    
    #2.取得した文字列を1文字ずつループ処理する
    str.each_char do |char|
      #文字色は31から36まで順に切り替え、最後まで進んだらまた31に戻る
      color = 31 + count % 6

      #3.各文字の手前にANSIエスケープシーケンスを付与する(さらに、文字を配列に追加する)
      colored_chars << "\e[#{color}m#{char}"

      count += 1
    end

    #4.各文字を連結して1つの文字列にする
    ret = colored_chars.join

    #5.最後に文字色をリセットするための\e[0mを付与する
    ret + "\e[0m"
  end
end

ターミナル

ruby test/rainbowable_test.rb 

rainbowable.rbのリファクタリング

module Rainbowable
  def rainbow
    colored_chars = []
    to_s.each_char.with_index do |char, count|
      color = 31 + count % 6
      colored_chars << "\e[#{color}m#{char}"
    end
    colored_chars.join + "\e[0m"
  end
end

さらにmapを用いてリファクタリング

module Rainbowable
  def rainbow
    to_s.each_char.map.with_index do |char, count|
      color = 31 + count % 6
      "\e[#{color}m#{char}"
    end.join + "\e[0m"
  end
end

あらゆるオブジェクトでrainbowメソッドを使えるようにする

rainbowable_test.rb

require 'minitest/autorun'
require_relative '../lib/rainbowable'

class RainbowableTest < Minitest::Test
  def setup
    # StringクラスやArrayクラスではなく、ObjectクラスにRainbowableモジュールをinclude
    Object.include Rainbowable
  end

  def test_rainbow
    expected = "\e[31mH\e[32me\e[33ml\e[34ml\e[35mo\e[36m,\e[31m \e[32mw\e[33mo\e[34mr\e[35ml\e[36md\e[31m!\e[0m"
    assert_equal expected, 'Hello, world!'.rainbow

    expected = "\e[31m[\e[32m1\e[33m,\e[34m \e[35m2\e[36m,\e[31m \e[32m3\e[33m]\e[0m"
    assert_equal expected, [1, 2, 3].rainbow

    # rainbowメソッドの戻り値をターミナルに出力
    # ハッシュや範囲オブジェクトなど、任意のオブジェクトに対してrainbowメソッドを呼び出してみる
    puts ({foo: 123, bar: 456}.rainbow)
    puts (10..20).rainbow
    puts true.rainbow
    puts false.rainbow
  end
end

スポンサーリンク