Ruby リファクタリング

最近は、コードを書いていて
短く書くかつ、わかりやすくかけるように意識しています
・コードレビューで指摘される
・普段からリファクタリングを意識して書くのでは大違いだと思うから
ということで、記法をいくつかみてまとめてみます

##繰り返し使う文字列をlocaleに定義する
コードをDRYにする
時刻のフォーマット等もlocaleを使い、strftimeは基本使わない。

###localeとは…
[Railsガイド](https://railsguides.jp/i18n.html)
住所、会社名、時間をフォーマットする時の形式、
今日の日付を出力する時の形式などを管理する。
[使い方](https://qiita.com/d0ne1s/items/89846ebe97c9114865ca)
これは、業務でも使っている。何度も使う文言とかをまとめている
テンプレのようなもの

##埋め込みRuby
文字の中にRubyの式を埋め込む

リファクタ前

```rb
name = '太郎'
puts "こんにちは、 " + name + "!"
#=> "こんにちは、太郎さん"
```

リファクタ後

```rb
name = '太郎'
puts "こんにちは、#{name}さん"
#=> "こんにちは、太郎さん"
```

`シングルクォーテーション`( '' )だと、
式展開されないので注意する

##三項演算子
リファクタ前

```rb
 def click_button
    if controller.action_name == 'new'
      puts "New"
    else
      puts "Nothing"
    end
  end
```

リファクタ後

```rb
 def click_button
  controller.action_name == 'new' ? puts "New" : puts "Nothing"
end
```

複雑なif文を書き換えるのには、向いていないので
なるべくシンプルな if else文で使うとよさそう

三項演算子をネストさせたりすると、かえって
可読性が悪くなる

##後置if
リファクタ前

```rb
 def walk
    if user.people?
      puts '歩きます'
    end
 end
```

リファクタ後

```rb
 def walk
    puts '歩きます' if user.people?
 end
```

こちらも、多用するのではなく
[こちらの記事](https://qiita.com/jnchito/items/4e47559a4c821474233a)を見るのがよさそう

##ぼっち演算子
```rb
 def find_currency(country)
   currencies = { japan: 'yen', us: 'dollar' }
   currencies[country]
 end

 def show_currency(country)
   currency = find_currency(country)
   if currency
     currency.upcase
   end
 end

 show_currency(:japan) => "YEN"
 show_currency(:brazil) => nil
```

さらにこう書ける

```rb
 def show_currency(country)
   #条件分岐内で直接変数に代入する(値が取得できれば真、できなければ偽)
   if currency = find_currency(country)
     currency.upcase
   end
 end
```
Rubyでは、変数への代入自体が戻り値を持つため、if文の中で
直接、変数に代入することも可能。
しかし、これだと「=」と「==」を書き間違えたのではと勘違いされる可能性もある。

`nilかもしれないオブジェクトに対して、安全にメソッドを呼び出したい`場合には
ぼっち演算子を使うことができる
メソッドを呼び出したオブジェクトが`nilではない`場合→**その結果**
メソッドを呼び出したオブジェクトが`nilだった`場合→**nil**
を、それぞれ返す

リファクタ後

```rb
  def find_currency(country)
   currencies = { japan: 'yen', us: 'dollar' }
   currencies[country]
 end

 def show_currency(country)
   currency = find_currency(country)
   currency&.upcase
 end
```

##||= (nilガード)
nilが入らないようにするもの
変数に値を入れるときに、変数が`nilかfalse`のときのみ値を入れることができる

```rb
pry(main)> user = nil
=> nil
pry(main)> user ||= '太郎'
=> "OK"
pry(main)> user
=> '太郎'
```

既に値が入っている場合は値の代入は行われない

```rb
pry(main)> user = '次郎'
=> '次郎'
pry(main)> user ||= '三郎'
=> '次郎'
```

##引数
メソッドにわたす引数の種類ですが、割とたくさんあるので
まとめます

###デフォルト引数
引数にデフォルト値を入れておいて、引数がなければデフォルト値を使用する

```rb
def putsHello(msg="No msg", name="No name")
  puts(msg + "," + name + "¥n")
end

putsHello("Hello", "Yamada") #=> 'Hello, Yamada'
putsHello("Hello") #=> 'Hello, No name'
putsHello() #=> 'No msg, No name'
```

###キーワード引数
・ハッシュを作成したときのように**シンボル: 値**で指定する
・デフォルト値の役割も果たす
・呼び出す際に、順番も自由に入れ替えることができる

```rb
def buy_burger(menu, drink: true, potato: true)
  if drink && potato
    puts "#{menu}バーガーセットとドリンクとポテトを頼みました"
  elsif drink 
    puts "#{menu}バーガーセットとドリンクを頼みました"
  elsif potato
    puts "#{menu}バーガーセットとポテトを頼みました"
  else
    puts"#{menu}バーガーセットを頼みました"
  end
end

buy_burger("cheese") #=> "cheeseバーガーセットとドリンクとポテトを頼みました"
buy_burger("cheese", drink: false, potato: true) #=> "cheeseバーガーセットとポテトを頼みました"
buy_burger("fish", potato: false, drink: false) #=> "fishバーガーセットを頼みました"
```

###可変長引数
・引数を配列として受け取ることができる
・引数名に*をつける

```rb
def order(*food)
  puts "#{food.join('と')},お願いします！"
end

order('ハンバーガー') #ハンバーガー,お願いします！
order('ハンバーガー','ポテト') #ハンバーガーとポテト,お願いします！
order('ハンバーガー','ポテト','コーラ') #ハンバーガーとポテトとコーラ,お願いします！
```

##参考記事
[チェリー本](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99%E4%BA%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AERuby%E5%85%A5%E9%96%80-%E8%A8%80%E8%AA%9E%E4%BB%95%E6%A7%98%E3%81%8B%E3%82%89%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%83%BB%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E6%8A%80%E6%B3%95%E3%81%BE%E3%81%A7-Software-Design-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA/dp/4774193976/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E3%83%97%E3%83%AD%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99&qid=1606951319&sr=8-1)
https://qiita.com/jnchito/items/dedb3b889ab226933ccf
https://qiita.com/d0ne1s/items/fabbc0df7c273cf04fc3
[三項演算子](https://qiita.com/lasershow/items/160c854e4256ba596ec5)
[三項演算子](https://pikawaka.com/ruby/ternary-operator)
[ぼっち演算子](https://qiita.com/yoshi_4/items/e987b698c1978d248cfc)