Ruby 引数を扱うメソッド

#Ruby 引数を扱うメソッド#
**※この記事は初心者の私がチェリー本で学習するにあたって新しく知ったことや考えたことアウトプットするための場として書いています。**
この記事は以下の情報を参考にして記述し、一部引用しています。
[プロを目指す人のためのRuby入門](http://gihyo.jp/book/2017/978-4-7741-9397-7)
##この記事の目的##

**引数を扱うメソッドのルールとどんな時に使えるかを理解するため**

---
###基本的な引数を扱うメソッド###
```
irb(main):001:0> def greeting(country)
irb(main):002:1> if country == 'japan'
irb(main):003:2> 'konnitiwa'
irb(main):004:2> else
irb(main):005:2> 'hello'
irb(main):006:2> end
irb(main):007:1> end
=> :greeting
irb(main):008:0> greeting
Traceback (most recent call last):
        3: from /Users/hiwillowz/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
        2: from (irb):8
        1: from (irb):1:in `greeting'
ArgumentError (wrong number of arguments (given 0, expected 1))
irb(main):009:0> greeting('japan')
=> "konnitiwa"
irb(main):010:0> greeting('usa')
=> "hello"

```
デフォルトで引数（）を設定せずにメソッドだけ呼び出すとエラーが出ます。
ただ`ArgumentError`は引数に関するエラーという原因がすぐわかるのでそんなに深刻なエラーでは無いと思います。

```
irb(main):023:0> def greeting(country = 'japan')
irb(main):024:1> country == 'japan'? 'konnitiwa':'hello';
irb(main):025:1> end
=> :greeting
irb(main):021:0> greeting
=> "konnitiwa"
irb(main):022:0> greeting('england')
=> "hello"
```
下から二番目の行ですね、デフォルトで引数を設定したため`greeting`だけでもエラーにならずに返り値がでてきてます。
ちなみに三項演算子を使って先程のコードをリファクタリングしています。

---
###可変長引数###
可変長？パッと見よくわからないですけれど、個数に制限の無い引数のことを**可変長引数**と言い、この**可変長引数**を使う時は**`*`を引数の前につける必要がある**らしいです。

```
irb(main):049:0> def greeting(*names)
irb(main):050:1> "#{names.join('＆')}\,Hello!"
irb(main):051:1> end
=> :greeting

irb(main):052:0> greeting('Mr_Johnson')
=> "Mr_Johnson,Hello!"

irb(main):053:0> greeting('Mr_Johnson','Miss_Smith')
=> "Mr_Johnson＆Miss_Smith,Hello!"
```
コードを書いてもよくわからないけど、とりあえず今は個数に制限が無いのとメソッドや配列と一緒に使うってことを覚えとく。

---
###メソッドのキーワード引数とハッシュ###


こちらも複数の引数を設定するものですが、可変長引数が配列や展開する場合に使うのに対してキーワード引数は真偽値などの処理を行う複数の引数を設定するもの？ですかね（ふわっとしかわからない...）

```
irb(main):065:0> def dinner(main, drink, desert)
irb(main):066:1> if drink
irb(main):067:2> end
irb(main):068:1> if desert
irb(main):069:2> end
irb(main):070:1> end
=> :dinner

irb(main):071:0> dinner('cheken', true, true)
=> nil

irb(main):072:0> dinner('fish')
Traceback (most recent call last):
        3: from /Users/hiwillowz/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
        2: from (irb):72
        1: from (irb):65:in `dinner'
ArgumentError (wrong number of arguments (given 1, expected 3))
```
２行目の`dinner('cheken', true, true)`何に対してのtrueなのかメソッドを見直さないといけないのでとても読みにくいです。
引数を指定しないとデフォルトの値を設定していないので`ArgumentError`が出ましたね。

```
irb(main):073:0> def dinner(main, drink: true, desert: false)
irb(main):074:1> if drink
irb(main):075:2> end
irb(main):076:1> if desert
irb(main):077:2> end;end
=> :dinner

irb(main):078:0> dinner('fish')
=> nil

irb(main):084:0> params = {drink: false, desert: false}
=> {:drink=>false, :desert=>false}
irb(main):085:0> dinner('water', params)
=> nil
```
第２、第３引数をハッシュで指定することで読みやすくなったのとデフォルト値を設定したので読みやすくなりました。
後はキーワード引数と一致するハッシュであればメソッドの引数として渡すことが出来る。

---

###ハッシュを使った疑似キーワード引数###
```
def dinner(main, options = {})
irb(main):097:1> drink = options[:drink]
irb(main):098:1> desert = options[:desert]
irb(main):099:1> if drink
irb(main):100:2> end
irb(main):101:1> if desert
irb(main):102:2> end
irb(main):103:1> end
=> :dinner

irb(main):104:0> dinner('fish')
=> nil

irb(main):105:0> dinner('meet', salad: true)
=> nil
```
キーワード引数にハッシュを置いてメソッド内で引数を設定するのが擬似キーワード引数？、とりあえずメソッド内で設定されてないキーワードを渡してもエラーがでないので、普通のキーワード引数を使った方が無難。

---
###任意のキーワードを受け取る引数###
```
irb(main):107:0> def dinner(main, drink: true, desert: true, **others)
irb(main):108:1> puts others
irb(main):109:1> if drink
irb(main):110:2> end
irb(main):111:1> if desert
irb(main):112:2> end
irb(main):113:1> end
=> :dinner

irb(main):114:0> dinner('cheken', drink: true, desert: false, soup: true)
{:soup=>true}
=> nil

irb(main):116:0> dinner('fish')
{}
=> nil
```
キーワード引数を使うメソッドに無いキーワードを渡す時に`**`をつけた引数を最後に用意することで、`**引数`にはキーワード引数で指定されていないキーワードがハッシュとして格納されるというもの。