Ruby on Railsの現場でよく見る書き方【実例あり】

# はじめに
こんにちは、[@ryokky59](https://twitter.com/ryokky59)と申します！
未経験からエンジニアになって1年経ちました！
今回はRailsを実務で1年間触ってきて、この書き方は最初に知っておけばスムーズにソースコードが読めたなぁと感じたことをまとめてみました！

この記事で実務と独学の壁がすこしでも埋められるお手伝いができたらいいなと思います！

# 対象読者

- 未経験からエンジニアを目指してRailsを勉強している方
- 普段は他言語を使っているけど今度はRailsを使う現場に行かれる方
- 自社以外のRailsの書き方を知ってみたい方

# Railsのいろんな書き方

## `埋め込みRuby`
文字列の中にRubyの式や変数を埋め込める

```ruby
user_name = "taro"
"こんにちは#{user_name}さん。今日は#{Date.today}です"
# => "こんにちはtaroさん。今日は2019-12-14です"
```

`""`(ダブルクォーテーション)じゃないとRubyが展開されないので注意です。

## `||=`
変数に値を入れるときに、変数がnilかfalseのときのみ値を入れることができます

```ruby
user1 = "taro"
user1 ||= "jiro"
user1 
# => "taro" ("jiro"が代入されていない)

user2 = nil
user2 ||= "jiro"
user2
# => "jiro" ("jiro"が代入されている)
```

## `後置if`

例えば以下のようなfalse側がいらないif文がある時

```ruby
if true
  "trueでhoge"
end
# => "trueでhoge"
```

こういう時は以下のように一行で書くことができます

```ruby
"trueでhoge" if true # => "trueでhoge"
```

例を挙げるとメソッドから抜ける時によく使われます(ガード節といいます。詳しくは[コチラ](https://qiita.com/mom0tomo/items/779b6e380dc01d3bda54 ))


```ruby
def puts_user_name(user_id)
  user = User.find_by(id: user_id)
  return if user.nil? # もしuserがnilだったらreturnでメソッドから抜ける

  puts user.name
end
```

## `三項演算子`

例えば以下のような普通のif文があるとき、

```ruby
if true
  puts("trueでhoge")
else
  puts("falseでhuga")
end
# trueでhoge
```

このような `if~else~end` で終わるようなif文であれば一行で以下のように書くことができます

```ruby
true ? puts("trueでhoge") : puts("falseでhuga") # trueでhoge
```



## `メソッドの引数`その1

メソッドの引数の書き方は `()`でも` `(半角スペース)でも大丈夫です。

```ruby
User.find(1) # => {id: 1, name: "idが1のユーザー"} 

User.find 1  # => {id: 1, name: "idが1のユーザー"} 
```

使い分けとしては例えば、上の三項演算子の例では`puts "trueでhoge"`みたいに`()`ではなく、` `(半角スペース)で書くと`SyntaxError unexpected ':'` がでてしまいます。
三項演算子は` `(半角スペース)で次にどの文字がきて欲しいかを予測します。
なので`puts "trueでhoge"` と書いてしまうと`puts`の次が` `(半角スペース)で`:`が来ることを期待しているのに`"trueでhoge"` が来ているのでエラーになります。

このように、`()`で囲って一つの文として評価されたいか、` `(半角スペース)で繋げて読みやすくするかを使い分けることができます。

## `メソッドの引数`その2
メソッドに渡す引数の種類もいくつか種類があります。

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

```ruby
def puts_string(string="文字列")
  puts string
end

puts_string # "文字列"
```

### キーワード引数
引数をハッシュで指定する。
実行するときにキーワードも指定する必要がある。
引数が複数だったり、明示的にしたいときに使われる。

```ruby
def puts_string(string:)
  puts string
end

puts_string(string: "文字列") # "文字列"
```

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

```ruby
def name_array(*name)
  p name
end

puts_name_array("taro", "jiro", "saburo")
# => ["taro", "jiro", "saburo"]
```

## `!◯◯（変数）`
変数の前に`!`を書くと中身を反転したbooleanの形(trueまたはfalse)に変換することができます

下記のように`string`という変数の前に一つ`!`をつけると反転してfalse、さらにもう一つ`!`をつけるとさらに反転してtrueを返します。

```ruby
string = "文字列"
string   # => "文字列"
!string  # => false
!!string # => true
```

変数の中身をnilにすると理解しやすいかもしれません

```ruby
nil_val = nil
nil_val   # => nil
!nil_val  # => true
!!nil_val # => false
```

## `%記法`

配列はよく％記法を用いて書かれます。

```ruby
%w(hoge huga foo bar) # => ["hoge", "huga", "foo", "bar"]
```

注意するところは配列の中身は必ずstringになるというところです

```ruby
%w(1 2 3) # => ["1", "2", "3"]
```

シンボルにすることもできます

```ruby
%i(new create delete) # => [:new, :create, :delete]
```

## `{}`
ブロックは `do~end` で書くことが多いかもしれませんが `{}` を使って一行で書く時に読みやすくすることができます。

```ruby
%w(hoge huga foo).each do |string|
  puts string
end
```

```ruby
%w(hoge huga foo).each{ |string| puts string }
```

この二つはどちらも同じ結果を返します。
`do` が `{` に、 `end` が `}` に置き換わっただけですね
ブロックの中身が短く単純な時に便利です。

```ruby
[1, 2, 3, 4].select { |item| item % 2 == 0 } # => [2, 4]
```

上のように `select` や `any?` など配列、ハッシュを扱うメソッドを使う時によく見られます

## `map(&:〇〇)`
こちらは先ほどの`{}`で囲むブロック分よりさらに短縮したような書き方です。

```ruby
users.map { |user| user.name } # => ["taro", "jiro", "saburo"]

users.map(&:name) # => ["taro", "jiro", "saburo"]
```

上の例ではオブジェクトのキーを指定して値を取り出しています
これはブロックをprocに変換しているからできます。
実際はmapメソッドだけでなく他の配列、ハッシュを扱うメソッドで使うことができます。

procとかは聞き慣れないかなと思うので参考記事を置いておきます
[Rubyのmap &:to_iとはなんなのか](http://a-records.info/ruby-map-ampersand-colon-to_i/)
[Ruby Procについて学ぶ](https://qiita.com/naotospace/items/0163d4f8803a63f5fb17)

```ruby
items.sort_by(&:created_at) # itemのcreated_atが古い順に並び替える
```

## `includes`
引数に書いたモデルを先読みしてキャッシュしておく。
簡単にいうと不要なSQLを発行しないようにしてパフォーマンス低下を防ぐ(N+1問題を防ぐ)

```ruby
@user = User.all.includes(:items)
```

↑のようにしておくと@user.itemsをeachで回したときにitem.nameとかでitemの数だけSQLが発行されるのを防ぐ
詳しくは下記記事を参考にどうぞ
[Rails で includes して N+1 問題対策](https://qiita.com/hirotakasasaki/items/e0be0b3fd7b0eb350327)

## `&.`(セーフナビゲーション)
別名`ぼっち演算子`
エラーの代わりにnilを返してくれます。

```ruby
# userのnameがnilのとき

user.name.length # => NoMethodError: undefined method `length' for nil:NilClass

user.name&.length # => nil
```

nilの値であるレシーバ(name)に対してlengthメソッドを実行するとエラーが出ますが、`&.`でチェーンすることでnilに変わります。
nilが入る可能性のあるカラムを操作するときによく使われます。

## `each_with_index`
eachで回すときにindexが欲しいときに使います。

```ruby
users = %w(taro jiro saburo)

users.each_with_index do |user, index|
  puts "user: #{user}, index: #{index}"
end

# user: taro, index: 0
# user: jiro, index: 1
# user: saburo, index: 2
```

indexを任意の数字で始めることもできます

```ruby
users = %w(taro jiro saburo)

# eachにチェーンしてwith_indexを繋げていることに注意
users.each.with_index(1) do |user, index|
  puts "user: #{user}, index: #{index}"
end

# user: taro, index: 1
# user: jiro, index: 2
# user: saburo, index: 3
```

# おわりに
現場では他にも色々書き方はあると思いますが、ここまでの内容を抑えておけばそこそこスムーズにソースコードを読めるのではないでしょうか？
他にも「うちではこんな書き方あるよ！」みたいな方はお気軽にコメントください！

# 他記事への参考リンク
これからRailsを触っていく方に役に立つなと感じたリンクです。
(一部この記事を書く際にも参考にさせていただきました。m(_ _)m)
[他言語経験者がRailsの案件にジョインしたときに、何を足掛かりにすべきか](https://qiita.com/Kirika/items/42d66e17d39fe944bf9d)
[差をつけるRuby](https://qiita.com/genya0407/items/45f035c0f4b61d448aa1)