Railsを利用したWeb APIのroutes.rbの設定検証

Railsを利用したWeb APIで, `some_domain/api/v1` 形式のURIにするための
routes.rbのnamespaceを利用した設定を検証します。

## <i class="fa fa-file-text-o" style="font-size:1em;"></i> 仕様
### <i class="fa fa-code" style="font-size:1em;"></i> Model
Person#name (string)
Person#age (integer)

### <i class="fa fa-code" style="font-size:1em;"></i> Files
* `app/models/person_model.rb`
* `app/controllers/people_controller.rb`
* `app/controllers/api/v1/people_controller.rb`

### <i class="fa fa-code" style="font-size:1em;"></i> HTML ViewのURI
|機能|Method|Path|Action|
|:--|:--|:--|:--|
|リスト参照|GET|/people(.:format)|people#index|
|登録|POST|/people(.:format)|people#create|
|登録画面|GET|/people/new(.:format)|people#new|
|編集画面|GET|/people/:id/edit(.:format)|people#edit|
|1件参照|GET|/people/:id(.:format)|people#show|
|更新|PUT|/people/:id(.:format)|people#update|
|削除|DELETE|/people/:id(.:format)|people#destroy|

### <i class="fa fa-gears" style="font-size:1em;"></i> API のURI
|機能|Method|Path|Action|
|:--|:--|:--|:--|
|リスト参照|GET|/api/v1/people(.:format)|api/v1/people#index {:format=>/json/}|
|登録|POST|/api/v1/people(.:format)|api/v1/people#create {:format=>/json/}|
|1件参照|GET|/api/v1/people/:id(.:format)|api/v1/people#show {:format=>/json/}|
|更新|PUT|/api/v1/people/:id(.:format)|api/v1/people#update {:format=>/json/}|
|削除|DELETE|/api/v1/people/:id(.:format)|api/v1/people#destroy {:format=>/json/}|

## <i class="fa fa-file-text-o" style="font-size:1em;"></i> プログラム
### routes.rb
```ruby:config/routes.rb
Rails.application.routes.draw do
  # namespaceを利用することで、 /api/v1/each_api 形式のrouting設定を行う
  namespace :api, format: 'json' do
    namespace :v1 do
      resources :people
    end
  end
  resources :people
  root to: 'people#index'
end
```

### HTML View Controller
※scaffoldしたまま。

### API Controller
```ruby:app/controllers/api/v1/people_controller.rb
require "#{Rails.root}/app/controllers/application_controller.rb"

module Api
  module V1
    class PeopleController < ApplicationController
      before_action :set_person, only: [:show, :edit, :update, :destroy]
      # 動作確認用にCSRFを無効化しています
      skip_before_action :verify_authenticity_token

      # GET /api/v1/people
      def index
        render json: Person.all
      end

      # GET /api/v1/people/1
      def show
        render json: PersonResource.new(Person.find(params[:id]))
      end

      # POST /api/v1/people
      def create
        @person = Person.new(person_params)
        if @person.save
          render json: @person
        else
          render json: @person.errors, status: :unprocessable_entity
        end
      end

      # PATCH/PUT /api/v1/people/1
      def update
        if @person.update(person_params)
          render json: @person
        else
          render json: @person.errors, status: :unprocessable_entity
        end
      end

      # DELETE /api/v1/people/1
      def destroy
        @person.destroy
        head :no_content
      end

      private
        # Use callbacks to share common setup or constraints between actions.
        def set_person
          @person = Person.find(params[:id])
        end

        # Never trust parameters from the scary internet, only allow the white list through.
        def person_params
          params.require(:person).permit(:name, :age)
        end
    end
  end
end
```

## <i class="fa fa-child" style="font-size:1em;"></i> HTML View 動作確認
※scaffoldしただけなので一覧だけ紹介

![web_api_html_view.png](https://qiita-image-store.s3.amazonaws.com/0/43480/01c31e4e-ca5f-268a-f6b0-15b4915fac65.png)


## <i class="fa fa-child" style="font-size:1em;"></i> API 動作確認
`curl`コマンドで動作確認します

### <i class="fa fa-users" style="font-size:1em;"></i> リスト参照
~~~bash
$ curl -X GET http://localhost:3000/api/v1/people
[{"id":1,"name":"tanaka","age":23,"created_at":"2015-07-15T07:29:24.210Z","updated_at":"2015-07-15T07:29:24.210Z"},{"id":2,"name":"suzuki","age":42,"created_at":"2015-07-15T07:29:34.840Z","updated_at":"2015-07-15T07:29:34.840Z"},{"id":3,"name":"honda","age":99,"created_at":"2015-07-21T06:27:41.264Z","updated_at":"2015-07-21T06:27:41.264Z"},{"id":4,"name":"seki","age":123,"created_at":"2015-07-28T07:46:24.991Z","updated_at":"2015-07-28T07:46:24.991Z"}]
~~~

### <i class="fa fa-user" style="font-size:1em;"></i> 1件参照
~~~bash
$ curl -X GET http://localhost:3000/api/v1/people/1
{"id":1,"name":"tanaka","age":23}
~~~

### <i class="fa fa-plus-circle" style="font-size:1em;"></i> 登録
~~~bash
$ curl -X POST -H "Content-Type: application/json" -d '{"person": {"name":"hoge", "age": "123"}}' http://localhost:3000/api/v1/people
{"id":7,"name":"hoge","age":123,"created_at":"2015-07-29T08:15:04.694Z","updated_at":"2015-07-29T08:15:04.694Z"}
~~~

### <i class="fa fa-refresh" style="font-size:1em;"></i> 更新
~~~bash
$ curl -X PUT -H "Content-Type: application/json" -d '{"person": {"name":"hoge_update", "age": "12345"}}' http://localhost:3000/api/v1/people/7
{"id":7,"name":"hoge_update","age":12345,"created_at":"2015-07-29T08:15:04.694Z","updated_at":"2015-07-29T08:26:35.564Z"}
~~~

### <i class="fa fa-trash" style="font-size:1em;"></i> 削除
~~~bash
$ curl -X DELETE http://localhost:3000/api/v1/people/7
# 削除成功
~~~