はじめに
今回Rubyを学習する上で使用した参考書の
プロを目指す人のためのRuby入門の感想について書いていきます。
良かったところ
各章で特定の分野について深いところまで解説してくれているのが良かったです。
コードの書き方を機械的に覚えてしまうことは多いと思うのですが
なぜそのような書き方になるのかなども丁寧に解説しています。
また本書籍では例題を通して実際にコードを書きながら学習ができるのですが
そのコードも現場を意識してより良いコードにするリファクタリングについての説明もしてくれるのがありがたいですね。
学んだこと
2章:Rubyの基礎を理解する
- 変数を宣言する際はスネークケース。
- 数字から始まる変数は宣言できない。
- 文字列作成の際はシングルクオートかダブルクオートを使用する。文字列の中で
\n
で改行を入れる際はダブルクオートを使用する。 - ダブルクオートの中で
#{}
を使用すると式展開を使用できる。式展開で文字列の中に変数の値や式の結果を埋め込める。 - nilとfalseは偽の値。それ以外は真の値。
-
require
でライブラリを読み込める。しかし、自作のプログラムを読み込む際はrequire_relative
3章:テストを自動化する
- テスティングフレームワークを使えばテストを自動化して実行結果を目視で確認する作業を省け、どこが間違っているかも教えてくれる。
- テストコードのクラス名は慣習としてキャメルケースでTestで始まるか、Testで終わる形にする。
- テストコードのファイル名はスネークケースでクラス名と合わせる。
4章:配列や繰り返し処理を理解する
- ブロック
- メソッドに渡せるブロックは一つ。
- ブロックの戻り値はメソッドと同様に最後に評価された式。
- ブロック内で宣言した変数はブロック内のみで使用可能。
- ブロック外で宣言された変数やメソッドはブロック内で参照可能。
- ブロックを書く際は以下のように
do
とend
で書くパターンと{}で閉じるパターンがある。前者はブロックが長くなる時に使い、後者の方は一行でコンパクトに書きたいときに使うケースが多い。codesample.each do |n| sum += n end
codesample.each {|n|sum += n}
- 範囲(Range)
-
1..3
のような書き方で値の範囲を表現できる。'a'..'c'
のように文字列でも使える。 -
1..3
で最後の値を含み、1...3
で最後の値を含まない。 - 以下のように配列の中の特定の値を取り出すときに便利。
code
irb(main):001> a = [1,2,3,4,5] => [1, 2, 3, 4, 5] irb(main):002> a[1..3] => [2, 3, 4]
-
5章:ハッシュやシンボルを理解する
-
ハッシュ
- ハッシュはキーと値の組み合わせでデータを管理するオブジェクト。
- 以下のようにeachでハッシュのキーと値を一気に取り出せる。
code
sample.each do |key,value| #ブロックパラメータにキー、値の順で入っていく puts "#{key}":"#{value}" end
codesample.each do |key_value| #ブロックパラメータが一つの場合はキーと値が配列として格納される。 key = key_value[0] key = key_value[1] puts "#{key}":"#{value}" end
- **を使うとハッシュの要素を展開できる。
code
irb(main):001> h = {us:'dollar',India:'rupee'} => {:us=>"dollar", :India=>"rupee"} irb(main):002> {japan:'yen',**h} => {:japan=>"yen", :us=>"dollar", :India=>"rupee"}
-
シンボル
- シンボルは
key:value
のように特定の文字列と対になるオブジェクト。 - イミュータブルなオブジェクトで破壊的な変更は不可能。
- ハッシュのキーとして使用されるケースが多い。
- シンボルは
6章:正規表現を理解する
- rubyにおける景気表現は
/正規表現/
の形で作成する。
マッチした場合は文字列の開始位置が表示される。しなかった場合はnilが返される。codeirb(main):003> '123-4567' =~ /\d{3}-\d{4}/ => 0
codeirb(main):004> '12-567' =~ /\d{3}-\d{4}/ => nil
-
scan
メソッドで正規表現でマッチした部分を配列に追加する。codeirb(main):006> '123 456 789'.scan(/\d+/) => ["123", "456", "789"]
- []に正規表現を渡すとマッチした部分を取り出せる。
slice
メソッドでも同様のことができる。codeirb(main):008> text[/\d{3}-\d{4}/] => "123-4567"
codeirb(main):009> text.slice(/\d{3}-\d{4}/) => "123-4567"
- 正規表現オブジェクト作成時のオプション
-
/正規表現/i
で大文字小文字の区別をしない。 -
/正規表現/m
で改行文字にもマッチするようになる。 -
/正規表現/x
でスペースや改行文字が無視されてコメントが正規表現ないに記載できるようになる。
-
7章:クラスの作成を理解する
- クラスをもとにしたデータの塊をオブジェクトまたはインスタンスと呼ぶ。呼び出したメソッドに対するオブジェクトをレシーバーと呼ぶこともある。
- 呼び出したレシーバーのメソッドをメッセージと呼ぶ場合がある。これはSmalltallkという言語から影響を受けてのもの。
- 作成したオブジェクトごとに保持しているデータは異なりそのデータのことを状態(ステート)と呼ぶ。
- 作成されたオブジェクトから取得できる
user.first_name
のような値のことを属性(アトリビュート、プロパティ)と呼ぶ。 - クラスないで共有される変数をインスタンス変数と呼ぶ。@で始まる変数名で定義される。
- インスタンス変数を外部から読み書きできるようにするために
attr_accessor
メソッドが使える。また、読み込み専用のメソッドにattr_reader
、書き込み専用のメソッドにattr_writer
が使える。 - メソッド名の前にselfをつけることでクラスメソッドが定義できる。インスタンスに含まれるデータを使わない場合に使用する。クラスメソッドは
クラス名.メソッド名
で呼び出せる。 -
self
- インスタンス自身を表し、メソッド内部でメソッドを呼び出す際には
self.メソッド名
のように使う。また、self
は省略可能。 - セッターメソッド内ではローカル変数に値を誤って入れてしまうケースがあるため必ず
self
を使用する。codedef setter name = 'aaa' #ローカル変数としてのnameに値が入る end
codedef setter self.name = 'aaa' #インスタンス変数としてのnameに値が入る。 end
- インスタンス自身を表し、メソッド内部でメソッドを呼び出す際には
8章:モジュールを理解する
-
module モジュール名
でモジュールを定義。以降もクラスの書き方と一緒。 - is-aの関係の観点から継承を使うのに適していないケースで共通の機能を持たせたいときにモジュールを使う。
- クラス内に
include モジュール名
でモジュール内で定義したメソッドがインスタンスメソッドとして呼び出せるようになる。 - クラス内にモジュールで機能を追加することをミックスインと呼ぶ。
- モジュール内で記載したselfは
include
先のクラスのインスタンスになる。そのためモジュール内でミックスインしたクラスのメソッドと連携することができる。codemodule sample def sample_method1 #ミックスインしたクラスのメソッド sample_method1 end end
-
extend モジュール名
でモジュールのメソッドをクラスメソッドとして追加する。 -
クラス名.include/extend モジュール名
でもモジュールを呼び出せる。 - モジュールのメソッド内でミックスイン先のインスタンス変数の読み書きができる。しかしこれは設計として推奨されない。
- クラスの名前の衝突を避けるためにモジュール内にクラスを作成する名前空間としてモジュールが使われるケースがある。
モジュール名::クラス名
で参照できる。 - 名前空間つきのクラスを定義する方法は二通りある。
code
#入れ子にして書くケース module SampleModule class SampleClass #処理 end end
code#入れ子なしのケース class SampleModule::SampleClass #処理 end
9章:例外処理を理解する
- シンプルな例外処理の構文。実際のプログラムではあまり好ましくない
code
begin #例外が起きうる処理 rescue #例外が発生した際の処理 end
-
message
メソッドで例外発生時のエラーメッセージを表示する。codebegin #例外が起きうる処理 rescue => 例外オブジェクトを格納する変数(exeptionの省略形のeやexが使われることが多い) #例外が発生した際の処理 puts e.message end
-
backtrace
メソッドでバックトレース情報(メソッドの呼び出し履歴)表示する。codebegin #例外が起きうる処理 rescue => 例外オブジェクトを格納する変数(exeptionの省略形のeやexが使われることが多い) #例外が発生した際の処理 puts e.backtrace end
- 例外オブジェクトのクラスが一致した場合のみ例外を捕捉することができる。
code
begin #例外が起きうる処理 rescue 例外クラス(ZeroDivisonError、NoMethodError等) #例外が発生した際の処理 #rescue節は複数記載可能 puts e.backtrace end
-
raise エラーメッセージ
メソッドで意図的に例外を発生させることができる。 -
full_message
メソッドで例外のクラス名、エラーメッセージ、バックトレースを一度に取り出せる。 -
ensure
節を組み込むことによって例外の有無にかかわらず行う処理を加えられる。codebegin #例外が起きうる処理 rescue #例外が発生した際の処理 ensure #例外の有無にかかわらず行われる処理 end
10章:yieldとProcを理解する
-
yield
- 作成したブロックを呼び出せる。
code
def sample puts 'aaa' yield end
codesample do puts 'bbb' end
-
yield
に渡した引数に過不足になってもエラーは発生しない。 - &をつけることによってブロックをメソッドの引数として使える。引数を実行する際
call
メソッドを使う。codedef sample(&引数) 引数.call end
- 作成したブロックを呼び出せる。
-
Proc
- ブロックをオブジェクト化できる。Stringクラスでの文字列、Integerクラスの整数を表す。
-
Proc.new
にブロックを渡してProcのインスタンスを作成。呼び出す際はcall
メソッドを使用。codeProc.new do #処理 end
11章:パターンマッチを理解する
- rubyにおけるパターンマッチの基本構文。
code
case 式 in パターン1 #in節ではローカル変数の宣言や代入は=を使わずに行われる。パターン1がここではそれを指す。 パターン1にマッチした時の処理 in パターン2 パターン1にマッチせずパターン2にマッチした時の処理 else どちらにもマッチしなかった時の処理 end
- ローカル変数にハッシュを使うときに
in {キー:}
のように値を省略するとキーと同じ名前のローカル変数が作成される。 - パターンマッチではいずれの条件式にも当てはまらない場合は例外が発生する。
- パターンマッチではインスタンス変数が使用不可。
12章:Rubyのデバック技法を身につける
- バックトレースはプログラムが実行されてエラーが発生するまでのメソッド呼び出し履歴を示した情報。これを読み取ることがエラーの早期解決へつながる。
- コード内の変数に期待した値が入っていない時にはprintデバッグが有効。rubyでは
puts
、p
、メソッドを使って出力される値の確認を行う。 - デバッガを使用することでプログラムを1行ずつ実行しながら変数の中身の確認などができて効率が上がる(irbみたいなもの)。rubyのデバッガには標準ライブラリのdebugや外部ライブラリのByebugがある。
- 公式リファレンスは情報として網羅性が高いため不明点があれば確認するのはエンジニアとして避けては通れない。
- テストコードを書いておけばデバッグにかかる時間を短縮できる可能性がある。また、短縮できなかったとしてもテストコードを書いておくことは良い習慣。
13章:Rubyに関するその他トピック
- 現在TimeクラスとDateTimeクラスの機能に差はなくrequireの必要があるDateTimeクラスは非推奨となっている。
- 非推奨機能を使った場合はrubyの2.7.2以降では警告が出ない。よってプログラムの実行を
W:deprecated
オプションで行うかプログラム内でWarning[:deprecated]=true
と記載する必要がある。 -
Bundler
で大量のgemをどの環境でも同一のバージョンでインストールできる。これによりチーム内での開発環境の差異を小さくできる。
難しかったこと
本書籍で学習するには前提としてある程度プログラミング等の基礎知識が必要です。
例えば6章では正規表現を扱うのですが、
正規表現についての詳細な説明は省かれており知識のない方は事前学習が必要です。
私自身正規表現の学習が必要であったため該当の章に差し掛かった際には
正規表現について別に学習をしました。
最後に
読了して最初に思ったことが「難しかった。」でした。
ですがインプットに使う書籍としては情報量、説明のわかりやすさに関しては
間違いないと思います。今後は不明点があった際のリファレンス用の資料としても
使っていきより良いRubiestを目指していきたいです。