rails strong parametersの使い方とハマったところ

基本的なつかい方

送信する方はとりあえずjqueryでこんなイメージ

$.ajax({
  type: "POST",
  url: "https://example.com/books",
  data: JSON.stringify({
    title: 'タイトル',
    description: '説明'
  }),
  contentType: 'application/JSON'
});

今回使うテーブルはbooksでtitleとdescriptionカラムをもつ。modelはこんな感じ

class Book < ApplicationRecord
  validates :title, presence: true
  validates :description, presence: true
end

コントローラ

class BooksController < ApplicationController
  def create
    Book.create!(book_params)
    head :created
  rescue ActionController::UnpermittedParameters => e
    head :bad_request
  rescue StandardError => e
    head :internal_server_error
  end

  private
    def book_params
      params.require(:book).permit(:title, :description)
    end
end

ハマったところ

wrap_parameters

postで送信すると、送信したデータがparamsにcontroller名のハッシュとしてセットされる。例えば、/path/to/booksというURLに{ title:'タイトル', description: '説明' }をjson形式でpostするとparams[:book]とうハッシュにセットされる。json形式でなく、postするとそのままparams[:title]、params[:description]がセットされる。これは、wrap_parametersという機能らしくrailsのデフォルトの設定のままだとこのようになる。

requireの中のpermitで指定してない項目があってもエラーにならない

例えば上記の例で{ title:'タイトル', description:'説明', hoge:'ほげ' }みたいなデータを送信するとUnpermittedParametersがraiseされると思っていた。が、実際にはraiseされない。ただし、json形式でない形で送信した場合にrequireせずに以下のようなコードを書くとhogeは許可されていないのでUnpermittedParametersがraiseされる。

def book_params
  params.permit(:title, :description)
end
paramsにformatが自動で付与される

jsonで送信するとparams[:format]='json'という値が勝手にセットされて以下のようなエラーが出る。勝手につけたパラメータでエラーになるってよくわからないが、require(:book)みたいな使い方をされる前提なのかもしれない。

found unpermitted parameters: :format
パラメータ名がmodelと同じだとparamsの中身がフィルタリングされる

以下のプログラムにして{ title:'タイトル', description:'説明', hoge:'ほげ' }というデータを送信。permitに:hogeを追加したのにbook_paramsの中身には:hogeがなくなってる。

def create
  book_params ## book_params -> { title:'タイトル', description:'説明' }
  ・・・
end                                                                                                                                                                                                                                           
 
private
  def book_params
    params.require(:book).permit(:title, :description, :hoge)
  end

ちなみにbooksモデルを削除して実行したらbook_paramsに:hogeはちゃんといた。ちゃんとmodelと連携までしてるのか。裏で色々やってくれてるのでわからなくなる、、
わかりずらい文章だが、以上です