Rubyの基本的なメソッドと参照について学んだこと

# 目次
- Rubyのメソッド
- 参照の概念
- ライブラリ

---

# Rubyのメソッド
Rubyには標準でいろんなメソッドがあります。
また、自分でメソッドを定義することも可能です。

---
## メソッドに引数を設定する
![スクリーンショット 2020-03-21 17.43.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/f9343d0e-ced2-1829-5479-43078d7543c9.png)

```cry.rb
def cry(animal)
  if animal == 'dog'
    puts 'woof woof！'
  elsif animal =='cat'
    puts 'meow meow!'
  end
end
cry('dog') # -> woof woof！
cry('cat') # -> meow meow!
# 引数に過不足があるとエラーになる
# cry　-> `cry': wrong number of arguments (given 0, expected 1) (ArgumentError)
```

メソッドを定義する際引数を設定できます。
今回はcryというメソッド名で引数によって動物の鳴き声を出力するメソッドを定義しました。

---
## 引数にはデフォルト値をつけることも可能
![スクリーンショット 2020-03-21 17.37.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/001426f4-a638-1fc4-f93e-93417d0511d2.png)


```cry.rb
  def cry(animal: 'cat')
    if animal == 'dog'
      puts 'woof woof！'
    elsif animal =='cat'
      puts 'meow meow!'
    end
  end

  cry(animal: 'dog') # -> woof woof！
# 引数がない場合でもエラーにならない！
  cry # -> meow meow!
```

通常引数は呼び出し側（実引数）とメソッド定義側（仮引数）で数が一致している必要があります。
ですが、メソッド定義側でデフォルト値を設定することが可能です。
今回はcryというメソッド名で引数によって動物の鳴き声を出力するメソッドに
引数が存在しない場合はデフォルト値をcatとして定義しました。

---
## 標準出力で使われるメソッド

```
puts 'Hello World'
Hello World
=> nil

print 'Hello World'
Hello World=> nil

p 'Hello World'
"Hello World"
=> "Hello World"
```

メソッドを定義してターミナルに出力確認をする際今回の記事ではputsメソッドを使用していますが他にもターミナルに出力できるメソッドがあります。
irbを使用して確認して見た結果

`puts`
引数のオブジェクトをto_sメソッドで文字列に変換し、改行を加えて出力する。
戻り値: nil

`print`
引数のオブジェクトをto_sメソッドで文字列に変換し、改行ををせず出力する。
戻り値: nil

`p`
引数のオブジェクトをinspectメソッドで文字列に変換し、改行ををせず出力する。
戻り値: 文字列

---
## 真偽値を返すメソッド
![スクリーンショット 2020-03-21 18.04.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/810bf78e-5be6-66f4-d1d3-630f82beeb55.png)


```boolean.rb
# ?で終わるメソッドを自作する場合
def what_name?(name)
  name == 'bob'
end
p what_name?('tom') # -> false
p what_name?('bob') # -> true
```

真偽値を返すメソッドとしてメソッド名の終わりに？をつけたメソッドがあります。
※`"".empty?`や`"Hello World".include?(Hello)`など

自作する場合でもメソッド名に?をつけたほうが戻り値がわかりやすくなります。

---
## エイリアスメソッド

![スクリーンショット 2020-03-21 18.18.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/9e501283-4c51-a742-7c4b-d422bf8d818d.png)

```alias.rb
# メソッドを定義する

def hello
  puts 'Hello World!'
end
# aliasを設定する
alias greeting hello

# 元のメソッド名でも呼び出せ、aliasで設定した別名でも同様に呼び出すことができる
hello # -> Hello World!
greeting # -> Hello World!
```

Rubyにはメソッドに複数の名前をついている場合、自分で任意の名前
で定義することができます。
今回はhelloメソッドの名前をgreetingと別名で定義しました。

---
## Rubyの戻り値
```expression.rb
def expression
  hello = 'Hello World'
end
# retern分を記載しなくても最後に評価された式が戻り値として取得できる
p expression # -> Hello World
```

```expression.js
function expression() {
  let hello = "Hello World"
  // return hello
}
// return文を記載しなければ戻り値を取得できない
console.log(expression()) // -> undefined

function expression() {
  let hello = "Hello World"
  return hello
}
// return文を記載すれば戻り値を取得できる
console.log(expression()) // -> Hello World
```

Rubyのメソッドでは`return`を記載しない場合、
最後に評価されたものが戻り値になります。
これは他の言語と少し違います。
試しにrubyで`return`を記載しないで定義したメソッドと
javascriptで`return`を記載しないで定義したメソッドを比較してみます。

---
## 擬似変数

```pseudo_variable.rb
p true # -> true
p self # -> main
p __FILE__ # -> ファイル名
p __LINE__ # -> 行番号
p __ENCODING__ # -> エンコーディング

# 擬似変数に代入しようとすることはできない
# p __ENCODING__ = 'test' # -> Can't assign to __ENCODING__
```

Rubyには擬似変数と呼ばれる特殊な変数が存在します。
擬似変数は値を変更することはできません。

---
## 破壊的メソッド

```destroy.rb
lang = 'ruby'

# upcaseだと呼び出した文字列自身は変化しない
p lang.upcase # -> RUBY
p lang #-> ruby

#upcase!だと呼び出した文字列自身が変化する
p lang.upcase! # -> RUBY
p lang # -> RUBY
```

Rubyのメソッドにはオブジェクトの値そのものを変更してしまうメソッドが存在します。
今回は `upcase`,`upcase!`を使用して'ruby'という文字列を'RUBY'に変換します。
以下の出力結果を確認すると`upcase`の場合、変数aの値は変化していません。
しかし、`upcase!`の場合変数aの値が変わっています。
このように破壊的メソッドを使用すると呼び出したオブジェクトの状態を変更することができます。

---
# 参照の概念
Rubyのメソッドが色々あるなか破壊的メソッドを用いた場合、値が書き換わりました。

実際にはRubyの変数に代入すると変数に値が格納されるわけではありません。
変数にはオブジェクトの参照情報が格納されます。

---
## メモリ領域
　
![study_night_boy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/569966f9-5ca5-e574-c1c3-3164fe35f194.png)

 パソコンがしてくれる作業を僕ら人間に当てはめるとこんな感じになります。

　1. 考える脳みそ -> CPU
　
　2. 作業する机 -> メモリ
　![スクリーンショット 2020-03-21 19.29.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/6aca278f-4cac-1c51-2c1f-f67e04538373.png)

変数に値を格納した時パソコンのメモリ領域（作業する机の領域）がどうなるかというとこんなイメージになります。
![スクリーンショット 2020-03-21 21.57.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/c78cbcfc-fbc2-278e-1619-2cbfb6e7f85a.png)
![スクリーンショット 2020-03-21 19.54.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/9319afe9-797c-c69d-023f-82284fec47fc.png)


```destroy.rb
lang = 'ruby'

# upcaseだと呼び出した文字列自身は変化しない
p lang.upcase # -> RUBY

# upcaseした際のオブジェクト番号を確認
p lang.upcase.object_id # -> 70178687801560

p lang #-> ruby
# 変数のオブジェクト番号を確認
p lang.object_id # -> 70178687801780

# upcase!した際のオブジェクト番号を確認
p lang.upcase!.object_id # -> 70178687801780
p lang # -> RUBY
# 変数のオブジェクト番号を確認
p lang.object_id # -> 70178687801780
```

ここで先ほどの破壊的メソッドについて戻ろうと思います。

`upcase`と`upcase!`でのオブジェクト番号を確認すると
`upcase`ではオブジェクト番号が違うため、新しくオブジェクトを生成し、そのオブジェクトの参照情報を格納しております。

`upcase!`ではオブジェクト番号が同一であることがわかります。
このことから変数にはオブジェクトへの参照が格納されており破壊的メソッドを使用することで、指定のオブジェクトの中身を書き換えているということがわかりました。

---
## ガベージコレクション（GC）
![スクリーンショット 2020-03-21 20.12.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/6f16a732-b11e-d1eb-d028-55f3bf74ce76.png)

パソコンがいろんな処理を行う際、作業机（メモリ領域）の場所を確保していきます。
作業机（メモリ領域）が場所が減っていくとそのうちスペースがいっぱいになってしまいます。
スペースがいっぱいになると僕ら人間が効率よく作業できないのと同様にパソコンも作業スペース
（メモリ領域）が減っていくと何もできなくなり処理が重たくなったり、最悪システムが停止したりします。
このようにメモリ領域が減っていく現象をメモリリークと言います。

このような状態にならないようにRubyにはガベージコレクションという機能が備わっています。
ガベージコレクションのおかげで僕らが作業スペースの後片付け（メモリの解放）をしなくても
使用されなくなったオブジェクトを片付けてくれます。
※家事代行サービスにお願いすればプロがよしなにやってくれる感じみたいですね。

---
# ライブラリ
<img width="849" alt="スクリーンショット 2020-03-21 22.31.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/6769560c-e9e0-9a88-07ae-3244fea35ce0.png">
Rubyでは最初から便利なプログラムがたくさん用意されています。
その便利なプログラムを寄せ集めたものをライブラリと言います。

---
## 組み込みライブラリ
![スクリーンショット 2020-03-21 20.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/932af9e5-987f-3794-6e39-f60b0d16f2cd.png)

```embedded_library.rb
text = 'Hello World'
p text.class # -> String
p text.methods.include?(:length) # -> true
p text.length # -> 11
```

人間でいうと本人の習得しているスキルのイメージです。
英語をネイティブレベルまで習得しているなら海外旅行に行って話す際、教科書を見なくても話せると思います。
※僕は英語話せませんが、、、

組み込みライブラリは Ruby 本体に組み込まれているため、わざわざ処理を実装しなくても
同様の処理をするプログラムが組み込みライブラリに存在していればそれを使用すれば良いのです。

今回は文字列の長さを取得する処理を実装するために、`String`クラスの`length`メソッドを使用しました。

---
## 標準ライブラリ

![スクリーンショット 2020-03-21 21.02.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/27bdc215-2ba4-69fa-3642-83b2037d487f.png)

スキルはまだ身についてないけど家にある本棚から書籍を使えばアプリ開発ができるのと同じように
標準ライブラリではあるものの、組み込みライブラリでないものについてはライブラリを読み込むことで使用することができます。

今回はTimeクラスに定義されているstrptimeメソッドを使用します。

```standard_library.rb
require 'Time'
p Time.strptime('2020-03-21T01:58:30+09:00', '%Y-%m-%dT%H:%M:%S%z') # -> 2020-03-21 01:58:30 +0900
```

---
## gem
![スクリーンショット 2020-03-21 21.20.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230985/b79c9343-7953-aa30-a885-0cb2b0043ffe.png)

スキルが身についていない、家の本棚にもない場合でも問題ありません。
Rubyでは偉大な先輩エンジニアの方々が外部ライブラリとして、[RubyGems](https://rubygems.org/)にアップロードしてくれています。
僕らは使いたいgemをそこからダンロードして、自分の端末にインストールすることで使用することができます。

今回はrails 5.2.3というgemをインストールして見ました。
`gem i -v 5.2.3 rails`

---

# 参考
[プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで](https://gihyo.jp/book/2017/978-4-7741-9397-7)

[値渡しと参照渡しの違いを理解する](https://magazine.rubyist.net/articles/0032/0032-CallByValueAndCallByReference.html)

[Rubyにおける（オブジェクトへの参照の）値渡しを理解しようとして無知を感じた](https://qiita.com/k-tokitoh/items/eecda14d9165660e9888)

[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word182.html)