Ruby基礎事項
配列・繰り返し処理
-
Rubyでは
for
文は使わない→each
メソッドを用いるnumbers = [1,2,3,4] sum = 0 numbers.each do |n| sum += n end
do-end
を使わない場合は{}
で囲うことも可能numbers.each { |n| sum += n }
-
以下の条件を満たす場合は、
&:メソッド名
が利用可能- ブロック引数が一つ
- ブロックの中で呼び出すメソッドには引数がない
- ブロックの中では、ブロック引数に対してメソッドを呼び出す以外の処理がない
[1,2,3,4,5,6].select(&:odd?)
-
配列に範囲内の値を入れる際は
to_a
メソッドを用いる(1..5).to_a
-
rjust
メソッドの利用で、桁数の調整が可能'0'.rjust(5) '0'.rjust(5, '0') '0'.rjust(5, '_')
デフォルトは空白で桁揃えされているが、第2引数を指定すると空白以外の文字列を埋めることができる。
-
配列の結合時
concat
は破壊的、+
は非破壊的 -
break
は一番内側のループを抜ける。throw-catch
は一番外側のループまで抜ける。例外処理とは関係ない。例外処理はraise-rescue
を使用する。 -
redo
はその回の繰り返し処理の最初に戻る。実装時には無限ループにならないように、回数のカウントを行う。イタレーションとか行う際に、基準以下ならやり直し、カウントオーバしたら続行みたいなのに使いそう。ハッシュ・シンボル
-
ハッシュの記法
hash = { key1 => value1, key2 => value2 }
-
シンボル
- 記法
:シンボルの名前
- 同じシンボルであれば、全く同じオブジェクトである(
.object_id
を比較すると同じ)。例えば、大量の同じ文字列と、大量の同じシンボルを作成した際は、シンボルの方がメモリ効率は良い。 - ただし、シンボルはイミュータブルなので破壊的な変更は不可能。
- 実用例を見ると、シンボルをハッシュのキーにすることで、文字列よりも高速に値を取り出すことができる。
- 記法
-
使用頻度の高いメソッド
keys
:ハッシュのキーを配列として返すvalues
:ハッシュの値を配列として返すhas_key?/key?/include?/member?
:ハッシュの中に指定されたキーが存在するかどうか確認するメソッド。
-
想定外の引数は
**
に吸収することができる。def buy_burger(menu, drink: true, potato: true, **others)
としておけば、想定外の入力が会った際も、
others
にハッシュとして格納される。 -
ハッシュは
to_a
メソッドを使用することで配列に変換することが可能。逆に配列に対して、to_h
メソッドで配列をハッシュに変換することが可能。 -
自己代入(
||=
)limit ||= 10
は変数
limit
がnil
またはfalse
であれば、10を代入する(それ以外はlimit
のそのままの値を用いる)という意味になる。- Rubyでは
nil
またはflase
であれば偽、それ以外は真とみなされる。
正規表現
- Rubyでは
-
正規表現と文字列を比較する際には、
=~
が使用される。マッチすると文字列中のマッチした位置が返る。マッチしなかった場合にはnil
が返る。 -
キャプチャには
match
メソッドを使用する。ただし、そのままmatch
メソッドを使用すると配列に連番で格納されてしまうため、「何番目が何の値か」を意識する必要がある。 -
よく使われるメソッド
scan
:引数で与えた正規表現にマッチする部分を配列にいれて返す。[], slice, slice!
:文字列から正規表現にマッチした部分を抜き出す。split
:正規表現を渡すと、マッチした文字列を区切り文字にして文字列を分解して、配列として返す。gsub, gsub!
:第一引数の正規表現にマッチした文字列を第二引数の文字列で置き換える。- キャプチャを用いた場合は
\1, \2
のようにしてキャプチャした文字列を連番で使用可能 - 名前付きキャプチャの場合は
k<name>
のようにして参照できる - 第二引数にハッシュを渡して、変換のルールを指定することも可能。
-
\w
は[A-Za-z0-9_]
と同じ意味。 -
正規表現オブジェクトの作成方法
//
:文字列内にスラッシュを使用する際はエスケープする必要がある。%r{}, %r!!
:囲む文字列次第でエスケープが不要になる。
-
正規表現オブジェクトのオプション
- 定義:
/正規表現/オプション
i
:大文字・小文字を無視してマッチングを行うm
:任意の文字を表す.
が改行文字にもマッチするようになる。x
:空白文字(改行文字も)が無視され、#
を使って正規表現中にコメントがかけるようになる。regexp = / \d{3} # 郵便番号の先頭3文字 - # 区切り文字のハイフン \d{4} # 郵便番号の末尾4文字 /x
- 定義:
-
$
で始まる組み込み変数もある。$&
:マッチした部分全体$1, $2,...
:キャプチャの取得$+
:最後のキャプチャ文字列の取得
クラスの作成
- クラス名は大文字で始める。慣例としてキャメルケースで書く。
- コンストラクタは
initialize
メソッド(外部から呼び出すことは不可能)。 - インスタンス変数は
@
で始める - インスタンス変数の値を読み書きするメソッドのことを「アクセサメソッド」という(ゲッターとかセッター)。単にインスタンス変数の内容を外部から読み書きするのであれば、
attr_accessor
というメソッドを使う。 - インスタンスに含まれるデータは使わないメソッドを定義したい場合もある→クラスメソッド
- 定義方法:メソッド名の前に
self.
をつける。
- 定義方法:メソッド名の前に
- テスト実行時
Minitest
ではsetup
メソッドを定義すると、テストメソッドの実行前に毎回setup
メソッドが呼び出される。 - セッターメソッドを呼び出したい場合は必ず
self
をつける。 - クラスの継承を行う場合は以下のように定義する。
class DVD < Product end
- 継承時にメソッドを書き換える場合はスーパクラスと同じ部分は
super(重複する部分1,重複する部分2)
と表記することで省略可能
- 継承時にメソッドを書き換える場合はスーパクラスと同じ部分は
- メソッドの公開レベル(JavaやC#とは若干異なる)
- public : クラスの外部からも自由に呼び出せる。
- private : クラスの内部のみで使用可能。クラスの内部で
private
と記載すると、それより下に記載にたメソッドはprivateとなる。ただし、クラスメソッドは対象外。 - クラスメソッドをproivateにしたい場合は、
class << self
の構文を使用する。 - privateメソッドでは
self
付きで呼び出すとエラーになる。 - 他の言語と異なり「privateメソッドはそのクラスだけでなくサブクラスでも呼び出せる」。
- protected : そのメソッドを定義したクラス自身と、そのサブクラスのインスタンスメソッドからレシーバ付きで呼び出せる。
- クラスの外部から定数を参照する場合は
クラス名::定数名
という構文を用いる。
- 定数の際代入を防ぐ場合には
.freeze
メソッドを使用する。あまり使わないらしい。
- 定数の際代入を防ぐ場合には
- クラスをネストさせた場合は
外側のクラス::内側のクラス
を使って参照が可能
- 等値を判断するメソッド
equal?
:object_id
が等しい場合にtrue
を返す。==
:オブジェクトの内容が等しいかどうかを判定eql?
:ハッシュのキーとして2つのオブジェクトが等しいかどうかを判断する。===
:case文のwhen節で使用される。
オブジェクト.メソッド名
と記述すると、特定のオブジェクトにだけ結びつくメソッドを定義することができる。→特異メソッド
モジュール
- モジュールの定義
module モジュール名 # モジュールの定義(メソッドや定数など) end
定義方法としては
class
に似ているが、モジュールからインスタンスを生成することはできず、ほかのモジュールやクラスを継承することはできない点がクラスとは異なる。 - モジュールはクラスに
include
して機能を追加することが可能(ミックスイン)。 - ミックスインする方法として
extend
もある。extend
を使うとモジュール内のメソッドをそのクラスと特異メソッド(クラスメソッド)とすることが可能。 - UFO演算子
a<=>b
- aがbより大きいなら正の整数
- aとbが等しいなら0
- aがbより小さいなら負の整数
- aとbが比較できない場合は
nil
- 実務的にモジュールの使用方法を考える場合は、名前空間の使用時が多い。クラス名の重複を防ぐ。モジュールないにクラスを定義すれば、同名のクラスがあってもモジュール名が異なれば衝突は起きない。使用方法は
モジュール名::クラス名
で指定。 - モジュールではミックスインとしても使えて、モジュールの特異メソッドとしても使えるメソッドを定義することができる。
module_function
メソッド。 - モジュールを
prepend
した場合は、ミックスインしたクラスよりも先に、モジュールからメソッドが検索される。 refinements
を使用すると、オーバーライドしたライブラリやメソッドのスコープを指定することができる(モジュールもrefine
可能)。有効にするときは使いたいクラスでusing モジュール名
とする。
例外処理
- 例外を補足して、処理を続行する場合は
begin # 例外が起きうる処理 rescue # 例外が発生した場合の処理 # rescueの右に補足したい例外クラス名を記載すると、例外オブジェクトのクラスが一致した場合のみ、例外を補足することができる。 end
- 例外が発生した場合、処理を中断して、メソッドの呼び出しを一つずつ戻っていく。メソッド呼び出しを戻る途中にその例外を補足するコードがあれば、そこから処理を続行できる。
- 通常のプログラムで補足するのは、StandardErrorクラスか、そのサブクラスに限定すべき。
- 補足する順番(継承関係)に注意しないと、永遠に補足されない例外処理を記載することになる。→サブクラスから順番に記載する。
- ネットワークエラーのように一時的に発生している問題の対処方法として
retry
コマンドがある。実装としては、カウンタ変数を用意して回数に制限をしないと、無限ループになる。
rescue => e
と書いて、e
にエラーメッセージを格納できる。- 意図的に例外を発生させる場合は
raise
を行う。 - 例外処理を入れた場合、例外の発生有無にかかわらず実行したい処理は
ensure
節を加える。また、例外が発生しなかった場合の分岐としてelse
節も追記可能。 rescue
は修飾子としても使用可能例外が発生しそうな処理 rescue 例外が発生した時の戻り値
- Rubyでは最後に発生した例外は組み込み変数の
$!
に格納。バックトレース情報は$@
に格納される。コードの可読性の観点から、組み込み変数はあまり使わない。 rescue
内でraise
することも可能→rescue
でログメール送信などの処理をしたのちに、補足した例外を再度発生させて、プログラム自体は異常終了させる。
yieldとProc
yield
はブロックに引数を渡したり、ブロックの戻り値を受け取ったりできる。- ブロックをメソッドの引数として、明示的に受け取ることもできる。ブロックを引数として受け取る場合は引数名の前に
&
をつける。また、そのブロックを実行する場合はcall
メソッドを使う。 - ブロック引数の個数は
arity
を用いて確認可能。def greeting(&block) puts 'おはよう' text = if block.arity == 1 yield 'こんにちは' elsif block.arity == 2 yield 'こんに', 'ちは' end puts text puts 'こんばんは' end
- ブロックをメソッドの引数として、明示的に受け取ることもできる。ブロックを引数として受け取る場合は引数名の前に
Proc
クラスはブロックをオブジェクト化するためのクラス。- 作成方法
Proc.new { |a, b| a + b } proc { |a, b| a + b } ->(a, b) { a + b } lambda { |a, b| a + b }
- Procオブジェクトを実行する方法
add_proc = Proc.new { |a,b| a + b } add_proc.call(10, 20) # callメソッド add_proc.yield(10, 20) # yieldメソッド add_proc.(10, 20) # .()を使う add_proc[10, 20] # []を使う
デバッグ方法
- 作成方法
- 例外クラスとその原因(概要)
- NameError:タイポや
require
を忘れている場合 - NoMethodError:メソッド名のミス、レシーバの方が想定していた型と異なる。レシーバが
nil
になっている。 - TypeError:期待しない型がメソッドの引数に渡されたときに発生する。
- ArgumentError:引数に型が違ったり、期待する値ではなかったりした場合
- SystemStackError:システムスタックが溢れた時に発生する。
- NameError:タイポや
Byebug
という外部ライブラリ。
その他
- RubyにはコードからAPIドキュメントを生成するツールが付属している。
RDoc
用のコメント文を作成してrdoc PATH
実行するとHTML形式のファイルが生成される。
-
二重コロンとドットの違い
- 名前空間を区切ったり、定数を参照する場合は二重コロンを用いる
- メソッドを呼び出す際はドットを使う。
module Sample class User NAME = 'Alice'.freeze def self.hello(name = NAME) "Hello, I am #{name}." end end end
Sample::User::Name #=> "Alice"
Sample::User.hello #=> "Hello, I am Alice." FileUtils
モジュールは基本的なファイル操作をまとめているものCSV
ファイルを読み書きする場合はCSVクラスが使えるYAML
もyamlクラスで扱える- RakeはRubyで作られているビルドツール。MakeのRuby版。
コメント