RailsのStrongParametersと友だちになった

# TL;DR
## StrongParametersとは
[StrongParameters](http://api.rubyonrails.org/classes/ActionController/StrongParameters.html) は, [require](http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-require) と [permit](http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit) からなる Action Controller のパラメータです。

## 何ができるんだろう
ユーザから意図しない構造で渡ってきたパラメータに対して、コントローラおよび早期の段階で例外として処理できます。

`require`: 指定した値が存在しなければ例外を出す
`permit`: 許可してない構造のオブジェクトをパラメータから除外する

## 何が嬉しいんだろう
コントローラの先（モデル、ファクトリ、リポジトリなどなど）で値の構造に関する例外について考えなくてよくなります。
つまり、StrongParametersを通していれば、以降受け取った値そのものだけにフォーカスできるんです。
都度、もし値がArrayじゃなかったらどうしようとか、Hashの構造違ったらどうしようとか考えなくていい、優しい世界になるはず！

# 実践
## require
`require` は必須項目のようなものです。
つまり、 `require` を利用すると、必要とする指定のパラメータのみを取り出すことができます。
例えば、パラメータから要求した対象の値だけをとりだすことができます。

```ruby:requireで必要な情報を取る
received_json = {
  name: 'Bob',
  books: [
    { book_code: 0, title: 'Title_0' },
    { book_code: 1, title: 'Title_1' },
    { book_code: 2, title: 'Title_2' },
  ],
}

params = ActionController::Parameters.new(received_json)

params.require(:name)
# => 'Bob'

params.require(:books)
# => [
#      {"code"=>0, "title"=>"Title_0"},
#      {"code"=>1, "title"=>"Title_1"},
#      {"code"=>2, "title"=>"Title_2"},
#    ]
```

必要とする指定のパラメータがなければ、もちろん例外(`ParameterMissing`)を出します。

```ruby:必要な情報がなかった。。。
params.require(:age)
# => ActionController::ParameterMissing: param is missing or the value is empty: age
```

## permit
`permit` はホワイトリストのようなものです。
つまり、`permit` を利用すると、意図した構造以外を除外することが出来ます。
例えば下記の場合、name 以外のパラメータは意図した構造外の値になるので除外されます。

```ruby:nameだけ許可するよ
received_json = {
  name: 'Bob',
  books: [
    { book_code: 0, title: 'Title_0' },
    { book_code: 1, title: 'Title_1' },
    { book_code: 2, title: 'Title_2' },
  ],
}

params = ActionController::Parameters.new(received_json)

params.permit(:name)
# Unpermitted parameters: books
# => {"name"=>"Bob"}
```

`permit` は構造を保証してくれるものなので、下記のような books 単体では除外されます。
一見すると上手くいってくれそうなものですけれどもね…

```ruby:booksだけ許可するよ
params.permit(:books)
# Unpermitted parameters: name, books
# => {}
```

仮に、例に上げた books のような構造を許可したい時には下記のようになります。

```ruby:books中のbook_codeとtitleだけ許可するよ
params.permit(:books => [:book_code, :title])
# Unpermitted parameters: name
# => {
#      "books"=>[
#        {"book_code"=>0, "title"=>"Title_0"},
#        {"book_code"=>1, "title"=>"Title_1"},
#        {"book_code"=>2, "title"=>"Title_2"}
#      ]
#    }
```

例に上げた params のような構造を許可したい場合は下記のようになります。

```ruby:nameとbooks中のbook_codeとtitleだけ許可するよ
params.permit(:name, :books => [:book_code, :title])
# => {
#      "name"=>"Bob",
#      "books"=>[
#        {"book_code"=>0, "title"=>"Title_0"},
#        {"book_code"=>1, "title"=>"Title_1"},
#        {"book_code"=>2, "title"=>"Title_2"}
#      ]
#    }
```

しれっと書きましたが、実は上記のような書き方はおすすめできないです。
アロー演算子は後方にある要素全てを指し示すため、意図しない値まで差されて暴れることがあるためです。

```ruby:暴れるアロー演算子
params.permit(:books => [:book_code, :title], :name)
# => SyntaxError: unexpected ')', expecting =>
```

なので、Object単位でカーリーブレイスでカバーしてあげましょう。

```ruby:包み込まれたアロー演算子
params.permit({:books => [:book_code, :title]}, :name)
# => {
#      "name"=>"Bob",
#      "books"=>[
#        {"book_code"=>0, "title"=>"Title_0"},
#        {"book_code"=>1, "title"=>"Title_1"},
#        {"book_code"=>2, "title"=>"Title_2"}
#      ]
#    }
```