Rubyのちょっとした使い方まとめ

---
あくまでメモ用です。
間違った解釈等あればコメントの方で教えていただければ修正いたします。

---

## <=>演算子について
<=>演算子を定義するクラスは一般にComparableモジュールをミックスインとしてインクルードする。
ミックスインについて理解できていないため、下記記事を参考にしてみます。
[今更聞けない! Ruby の継承と mixin の概念を継承リストから学ぶ](https://qiita.com/pink_bangbi/items/2c2f17516cd3a7b4eeac)


## to_〇〇について
### 明示的な変換
- to_s ... Stringへの変換　(Object型のinspectはto_sを呼び出す)
- to_i ... Integerへの変換
- to_f ... Floatへの変換
- to_a ... Arrayへの変換
- to_c ... Complexへの変換
- to_r ... Rationalへの変換

### 暗黙の変換
以下は暗黙の変換をさせても良いときに実装する。
実装していない場合は、暗黙の型変換は行われない。
- to_int ... Integerへ
- to_ary ... Arrayへ
- to_hash ... Hashへ
- to_str ... Stringへ

## 式展開された変数
""の中で式展開された変数は自動的にStringに変換される。


## フリーズ系
- s.freeze  ... sをイミュータブルにする。([イミュータブル](https://ejje.weblio.jp/content/immutable))
- s.frozen? ... sがフリーズされているか調べる。
文字列ならば、

```rb
s = 'string'
s.freeze
s.frozen? # true

s2 = +s  # 凍結されていた場合、凍結状態の文字列の凍結されていないものを複製して返す
s2.frozen? # false
```

[文字列の単項演算子(+)](https://docs.ruby-lang.org/ja/2.5.0/method/String/i/=2b=40.html)を用いることで、凍結状態のものと同じ文字列を持った凍結されていない文字列を作成することができる。


## 汚染
- s.taint    ... sに汚染済みマークを付ける
- s.tainted? ... sが汚染されているか調べる
- s.untaint  ... sの汚染済み状態を外す

ユーザ入力等は自動的に汚染マークを付けられる。


## オブジェクトのコピー
[clone,dup](https://ref.xaio.jp/ruby/classes/object/clone)
- clone ... オブジェクトの凍結状態、汚染状態、信頼状態、特異メソッドをコピーする.
- dup   ... 汚染状態と信頼状態をコピーするが、凍結状態、特異メソッドはコピーしない.
##### 浅いコピー
オブジェクト内に持っているインスタンス変数等もコピーされるが、指す先は同じものであるため、
コピー先で破壊的なメソッドを呼び出すとコピー元も変更される。


## 変数への代入をした際の識別子の扱い

```rb
class example
  def x; 1; end  # 必ず1を返すxという識別子のメソッド

  def test
    puts x  # 上のメソッドを呼び出す

    x = 0 if false

    puts x  # nilが出力

    x = 2
    puts x  # 2
  end
end
```

上記のように、識別子に対する代入を検出していれば、その識別子をローカル変数として扱う。


## 多重代入の注意点

```rb
puts x,y=1,2  # 1,2とは出てくれない。(xとy=1と2を出力しようとする。)

puts ((x,y=1,2)) # 1,2と出る！
```


## フリップフロップ

```rb

[1,2,3,4,'string',5,6].each do |x|
  print x if x==3..x==5
end
```

こんなの。左辺がtrueになると、右辺がtrueになるまで左辺が評価されず、右辺の評価が続く。
この場合、```34string5```という出力となる。


## シンボル

":"から始まるもの。
Rubyでは、メソッド名やクラス名、メンバ名、定数名などを数値で管理しており、その整数をコード上で表現したのがシンボル。シンボルと数値は１対１対応している。
速度が早いため、ハッシュのキーなどにすると良い。
respond_toメソッドは引数に指定したメソッドを持っているか調べるメソッド。

```rb
'str'.respond_to? :length  # true
'str'.respond_to? :a  # false

hash = { one: '1', two: '2' }
p hash[:one]  # "1"
```

#### 参考記事
[Rubyの文字列とシンボルの違いをキッチリ説明できる人になりたい](https://qiita.com/Kta-M/items/53a13ef60e14fcb41193)


## ヒアドキュメント
イメージでは、書いたまんまに使える文字列<br>
下記のように書くとダブルクォーテーションで文字列を囲っている時と同じように、エスケープ文字を許容する。

```rb

puts <<EOS
line1
line2
EOS
```

```puts "line1\nline2"```と同じ

逆に、エスケープ文字を認めたくないときには、上記でいう、EOS のようなセレクタをシングルクォーテーションで囲ってやるとできる。

```rb

puts <<'EOS'
\t\t\t\t
aaaaa
EOS
```

```puts '\t\t\t\t';puts 'aaaaa'```と同じ


## 定数の扱い

Rubyの定数はデフォルトでは変更可能であるため、freezeするのが好ましい。
(freezeしないと、Warningは出るものの、再代入する際に値を変えることができてしまう。)

#### 参考記事
[Rubyで定数を扱う場合はfreezeするべき](https://qiita.com/yukiyan/items/39f945c55b6dc5e11ed7)


## オブジェクトの等価性

### ```equal?```メソッド

2つのオブジェクトが同一のオブジェクトを参照しているか確かめるもの。

```rb
str1 = 'string'
str2 = 'string'
str1.equal? str2  # false
```


### ```==```演算子

Object型では、2つのオブジェクトのオブジェクト参照が等しいかどうかを確かめるためのもの。(equal?と同じ)
ほとんどのクラスでは、インスタンスは別でも値が等しいかテストできるように定義し直されている。
※```!=```は```==```演算子の実行結果を反転する。(```==```を実装していれば```!=```は使える。)

```rb
str1 = 'string'
str2 = 'string'
str1 == str2  # true
```

ArrayクラスやHashクラスにも```==```演算子は実装されており、等価とみなされる場合は、
#### Array
  - 要素の数が同じ
  - 対応するペアがどれも```==```で等しい場合

#### Hash
- キー/値のペアの数が同じ
- 対応するキーの値がそれぞれ等しい場合

※値は```==```演算子で比較されるが、ハッシュキーは```eql?```メソッドで比較される。


### ```eql?```
Object型では```equal?```の同義語として実装されている。
このメソッドをオーバライドしているクラスは型変換をしない厳格な意味での```==```として用いることが多い。

```rb
1 == 1.0    # true
1.eql? 1.0  # false
```


### ```===```演算子
「case演算子」と呼ばれる。
Object型:```==```演算子を呼び出すものとしてのデフォルトの```===```演算子を定義している。
多くのクラス:```==```の等価と変わらない。

いくつかのクラス:別の形で定義している。以下、その例

```rb
(1..10) === 5    # true  1..10の範囲内
/\d+/ === '123'  # true  正規表現(Regexpクラス)にマッチしている
String === 's'   # true  's'はStringクラスのインスタンス
:s === 's'       # false (Ruby2.5の環境下)
```
[Rangeクラス](https://docs.ruby-lang.org/ja/latest/class/Range.html)
[Regexpクラス](https://docs.ruby-lang.org/ja/latest/class/Regexp.html)


## 参考
[プログラミング言語Ruby](http://amzn.asia/6GsdNJD)