7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JSONが期待通りにcontrollerへ渡らない時の対処法

Last updated at Posted at 2014-09-17

概要

Strong Parameters 対応でattr_accessible 指定が排除された環境において、
仮想属性を含んだJSON データがPOST された際に、params のネスト部分にも仮想属性を含める方法について。

※仮想属性・・・DBにカラムを持たない仮想的な属性。確認用パスワードなどがその例。

事の発端

Strong Parameters 対応で、Post モデルからattr_accessible 指定を排除した。

Post.rb
 class Post < ActiveRecord::Base
   acts_as_paranoid
-  attr_accessible :created_at, :deleted_at, :user_id
-  attr_accessible :image_id, :note
-  attr_accessible :status
-  attr_accessible :version

このとき、Api::PostsController に渡るはずのパラメータが不足していた。

送信したJSON:

{
  "post": {
          "image_id": "1",
          "note": "test note"    
  }
}

期待したparams:

{"image_id"=>"1", "note"=>"test note", "post"=>{"image_id"=>"1", "note"=>"test note"}}

実際に渡ってきたparams:

{"image_id"=>"1", "note"=>"test note", "post"=>{}}

※image_id、note は共にPostモデルの仮想属性

解決策

Controller に以下の要領で、JSON のルートノードとネストパラメータに含めたい仮想属性名を記載する。

wrap_parameters :root_node_name, include: [:hash_key_1, :hash_key_2, …]

上の例であれば、次のように記載する。

Post.rb
class Api::PostsController < Api::ApplicationController
  wrap_parameters :post, include: [:image_id, :note]

理由

JSON データの場合、データを扱いやすくするようにRails がparams の加工を行っており、ネストされたパラメータの部分については次のように格納するパラメータを決定している。

  1. 明示的にオプション(attr_accessible、ParamsWrapper の:include や:exclude など)がある場合はそれに従ってハッシュを作る
  2. そうでない無指定の場合は各モデルのクラスメソッドattribute_names を叩くと返ってくるテーブルのカラム名に基づいてハッシュを作る

仮想属性でなければ、特にオプション指定をせずともattribute_names でカラム名が返るので下記のようにネストパラメータが生成される。

JSON データ: {"user": {"name": "xx", "age": "yy"}}
↓
controller に渡るデータ: {"name"=>"xx", "age"=>"yy", :user => {"name"=>"xx", "age"=>"yy"}}

しかし、仮想属性の場合は、attribute_names を叩いてもそれら属性名が返ることは無いので、オプション未指定ではネストパラメータに含める候補からから抜け落ちてしまっていた。

オプションの指定方法は上述「結論」の通り。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?