RailsをJSON APIとして使用する際、Jbuilderを使用すると便利です

例えばscaffoldを使用してUserの登録・表示アプリを作るとしましょう。

rails generate scaffold User name:string email:string password:string

チュートリアルにもあるようにこの一行で基本機能は完成します。

http://localhost:3000/users/new
でユーザを作成できます。
jb_new

http://localhost:3000/users
でユーザの一覧が表示されます。
jb_index

http://localhost:3000/users/1
で指定したIDのユーザ情報が表示されます。
jb_show

URLに.jsonを指定するとJSONフォーマットで出力してくれます。

http://localhost:3000/users.json

[
  {
    "id": 1,
    "name": "Taro",
    "email": "taro@example.com",
    "password": "pass_of_taro",
    "url": "http://localhost:3000/users/1.json"
  },
  {
    "id": 2,
    "name": "Jiro",
    "email": "jiro@example.com",
    "password": "pass_of_jiro",
    "url": "http://localhost:3000/users/2.json"
  }
]

http://localhost:3000/users/1.json

{
  "id": 1,
  "name": "Taro",
  "email": "taro@example.com",
  "password": "pass_of_taro",
  "created_at": "2015-03-12T13:09:40.000Z",
  "updated_at": "2015-03-12T13:09:40.000Z"
}

前置きが長くなりましたが、今回の本題はこのJSONです。
このJSONファイルのプロパティを制御しているのがJbuilderでapp/views/users以下にあります。

index.json.builder

json.array!(@users) do |user|
  json.extract! user, :id, :name, :email, :password
  json.url user_url(user, format: :json)
end

show.json.builder

json.extract! @user, :id, :name, :email, :password, :created_at, :updated_at

jsonキー

json.[キー]に任意のJSONキーを指定できます。
一覧表示のJSONを少しいじってみましょう。名前、Email、ユーザ表示URL、ユーザ編集URL(HTML)を取得します。

json.array!(@users) do |user|
  json.email user.email
  json.name user.name
  json.show_url user_url(user, format: :json)
  json.edit_url edit_user_url(user)
end
[
  {
    "email": "taro@example.com",
    "name": "Taro",
    "show_url": "http://localhost:3000/users/1.json",
    "edit_url": "http://localhost:3000/users/1/edit"
  },
  {
    "email": "jiro@example.com",
    "name": "Jiro",
    "show_url": "http://localhost:3000/users/2.json",
    "edit_url": "http://localhost:3000/users/2/edit"
  }
]

入れ子構造

JSONを入れ子にするには以下のように指定します
json.[親キー] do
json.[子キー]
 。。。
end
のように指定します。
ユーザ一覧のJSONを{users: […]}とオブジェクトにラップするには以下のようにします。

json.users do
  json.array!(@users) do |user|
    json.extract! user, :id, :name, :email, :password
    json.url user_url(user, format: :json)
  end
end
{
  "users": [
    {
      "id": 1,
      "name": "Taro",
      "email": "taro@example.com",
      "password": "pass_of_taro",
      "url": "http://localhost:3000/users/1.json"
    },
    {
      "id": 2,
      "name": "Jiro",
      "email": "jiro@example.com",
      "password": "pass_of_jiro",
      "url": "http://localhost:3000/users/2.json"
    }
  ]
}

.extract!

.extract!を使うとモデルから簡単にプロパティと値を取得できます。
json.extract! [モデル], [取得するプロパティ。。。]
ユーザ1のJSONからID、名前、Email、作成日を取得しましょう。

json.extract! @user, :id, :name, :email, :created_at
{
  "id": 1,
  "name": "Taro",
  "email": "taro@example.com",
  "created_at": "2015-03-12T13:09:40.000Z"
}

個々のプロパティを指定せずに全プロパティを取得する場合はRailsのattribute_names(テーブルの全カラム名を取得するメソッド)とSplat Operator(配列を一連の引数に変換する)を組み合わせる事で可能です。

json.extract! @user, *@user.attribute_names
{
  "id": 1,
  "name": "Taro",
  "email": "taro@example.com",
  "password": "pass_of_taro",
  "created_at": "2015-03-12T13:09:40.000Z",
  "updated_at": "2015-03-12T13:09:40.000Z"
}

以下のように指定しても良いようです。

json.merge! @user.attributes