「プロを目指す人のための Ruby 入門」を読んで Ruby を学び直した

11月末に出版された「プロを目指す人のための Ruby 入門」を読んだ.12月は少しバタバタしていて,読むのが遅くなってしまったけど,以下の企画に応募をしたら当選した.ありがとうございます👍

blog.jnito.com

はじめに

本書はタイトルに「入門」と書いてあるけど,正確にはプログラミングの入門書ではなく,最低限のプログラミングのスキルと Ruby のスキルが必要になる.まえがきにも似たようなことが書かれていて,その通りだなと思った.とは言え,本書はすごくキレイな流れで解説されているので,じっくり読み進めることで,プログラミング初学者でも十分ステップアップに活用できるようになっていた.なお,僕のスキルレベルとしては Ruby / Rails 歴3年ほどで,インフラの自動化を Ruby で書いたり,個人ツールを Rails で書いたりしている.また,TechAcademy で Rails 講師の副業を1年間続けている.

本書の良かったところ

例題 + テスト駆動開発

本書はほとんどの章に例題があり,実際に写経しながら進めることができる.さらに,テスト駆動開発で進めるようになっていて,テストコードを先に書いたり,テストを通しながらリファクタリングをする.この体験は素晴らしかった.

特に第4章にある「RGB 変換プログラム」のリファクタリングは良かった.最初,固定値でテストを通しつつ,DRY にリファクタリングをしながら変更し,最終的に1行になる.是非写経して欲しい.他にも第6章にある「Ruby のハッシュ記法を変換する」も,第7章にある「改札機プログラムの作成」も,本当に素晴らしい例題だった.

# Before
def to_ints(hex)
  r = hex[1..2]
  g = hex[3..4]
  b = hex[5..6]
  ints = []
  [r, g, b].each do |s|
    ints << s.hex
  end
  ints
end

# After
def to_ints(hex)
  hex.scan(/\w\w/).map(&:hex)
end

yield / Proc の解説

Ruby を学んでいると,yield / Proc あたりを理解できていることが中上級者になるポイントかなと思っているけど.本書では第10章で「ワードシンセサイザーの作成」という例題があり,3種類のエフェクトを Effects モジュールに実装し,さらに Proc を返すようになっている.Proc を写経しながら学べるのは非常に良かった.個人的にも yield / Proc を学び直すことができた.

module Effects
  def self.reverse
    ->(words) do
      words.split(' ').map(&:reverse).join(' ')
    end
  end

  def self.echo(rate)
    ->(words) do
      words.chars.map {|c| c == ' ' ? c : c * rate}.join
    end
  end

  def self.loud(level)
    ->(words) do
      words.split(' ').map {|word| word.upcase + '!' * level}.join(' ')
    end
  end
end

なお,メタプログラミングをさらに深く学ぶ場合は「メタプログラミング本」を合わせて読むと良いかと!

kakakakakku.hatenablog.com

「Ruby 技術者認定試験」の参考書にもなりそう

既に Ruby 資格の「Ruby Programmer Silver」と「 Ruby Programmer Gold」を取得しているけど,Ruby の言語仕様全般を学べるという意味では,参考書としても使えるなと思った.そのぐらい素晴らしい1冊だった.

kakakakakku.hatenablog.com

本書で学び直せたところ

正直,本書を読んで知った機能,そんなのもあったなーという機能が多くあり,Ruby を学び直すことができた.

Minitest

これまで Rails のテスティングフレームワークは RSpec を使っていたため,実は Minitest を使ったことがなかった.大規模なプロジェクトで使う場合は RSpec にメリットがあると思うけど,今回のように小さなスクリプトをテストする場合は Minitest も十分使えると思った.例えば,以下のように書くだけで,簡単にテストコードを書くことができる.あと,はじめて refute を見たときは,これはなんだっけ?と思った.

require 'minitest/autorun'

class SampleTest < Minitest::Test
  def test_sample
    assert_equal 'RUBY', 'ruby'.upcase
  end
end

splat 展開

メソッドの引数で可変長引数を受けるときなどに * を使うことはあるけど,配列の中に * を使って Array オブジェクトに展開する記法は知らなかった.今までは Range を使って (1..10).to_a のように書くことが多かった気がする.

# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
p (1..10).to_a
# Array
p (1..10).to_a.class

# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
p [*1..10]
# Array
p [*1..10].class

.each_with_index.each.with_index

配列に対して .each_with_index を使う場面は今までも多かったけど,添字を 0 以外にする方法があるのは知らなかった.表記が非常に似ているけど each.with_index(10) と書く.ようするに .each_with_indexeach.with_index(0) と同じと言える.使う場面あるかな?ドメイン次第ではあるかも.そもそも .each_with_index で添字を指定できるようになっていても良いような気もするけど.

fruits = ['apple', 'orange', 'melon']

# 0: apple
# 1: orange
# 2: melon
fruits.each_with_index {|fruit, i| puts "#{i}: #{fruit}"}

# 10: apple
# 11: orange
# 12: melon
fruits.each.with_index(10) {|fruit, i| puts "#{i}: #{fruit}"}

ブロックローカル変数

ブロック引数で変数名を ; で区切ることで,ブロック内部のローカル変数を宣言できるのは知らなかった.以下の例で言うと sum がブロックローカル変数になっている.知っておくと便利そうだけど,使う場面あるかな?OSS を読んでて出てきたら思い出してみようと思う.

numbers = [1, 2, 3, 4]
sum = 0

# 11
# 12
# 13
# 14
numbers.each do |n; sum|
  sum = 10
  sum += n
  p sum
end

# 0
p sum

例外専用の環境変数 $! と $@

これまた知らなかった.少しでもコード量を減らしたいときに使えそう.特に rescue => e と書かなくて良いのは便利そう.

begin
  1 / 0
rescue => e
  puts "#{e.class} #{e.message}"
  puts e.backtrace
end

begin
  1 / 0
rescue
  puts "#{$!.class} #{$!.message}"
  puts $@
end

プログラミング初学者にも読んで欲しいと思った第11章

最初にも書いた通り,僕は TechAcademy で Rails 講師の副業をしているため,日々プログラミング初学者に教えている.その中で,汎用的なスキルとして「エラーを楽しむこと」を強く伝えている.特にプログラミング初学者だと,エラーが出てうまく動かない場合にモチベーションが下がってしまうことがある.ただ,職業プログラマでもエラーなんて大量に出るし,重要なのはエラーの原因を特定して解決するスキルなので,バックトレースの読み方だったり,binding.pry の使い方だったりを教えている.また,シンタックスエラーはエディタの機能をフル活用しましょうという話もしている.そういう背景もあり,第11章の「Ruby のデバッグ技法を身につける」という内容は素晴らしかった.ここだけでも読んで欲しいと思った.

まとめ

  • Ruby スキルをステップアップするのに最高な1冊だった
  • 特に例題が素晴らしく,さらにテスト駆動開発を体験できる点も良かった
  • 仕事で Ruby / Rails を書いている人も学び直せる内容が多かった
  • 写経したコードは全て GitHub に push した

github.com

参考

本書に含まれなかった原稿も既に公開されている.合わせて読むと良いかと!

qiita.com