Rails-APIでTODOアプリを作る。

# はじめに
Rails５にrails-apiが取り込まれることになったので、
rails-apiを使って簡単なTODOアプリを作ってみましょう。

# 環境
Ruby 2.2.3
Rails 4.2.6

# 1.プロジェクトの準備

ビューに関連する機能は必要ないので、`rails-api`を使用します。

```bash
$ gem install rails-api
$ rails-api new todo-api
```

# 2.TODOリソースの作成

`title`と`description`を持つTodoモデルとコントローラを作成します。

```bash
$ bin/rails g scaffold todo title:string description:text
Running via Spring preloader in process 98946
      invoke  active_record
      create    db/migrate/20160405125716_create_todos.rb
      create    app/models/todo.rb
      invoke    test_unit
      create      test/models/todo_test.rb
      create      test/fixtures/todos.yml
      invoke  api_resource_route
       route    resources :todos, except: [:new, :edit]
      invoke  scaffold_controller
      create    app/controllers/todos_controller.rb
      invoke    test_unit
      create      test/controllers/todos_controller_test.rb
```


dbのマイグレーションをします。

```bash
$ bundle exec rake db:migrate
== 20160405125716 CreateTodos: migrating ======================================
-- create_table(:todos)
   -> 0.0014s
== 20160405125716 CreateTodos: migrated (0.0015s) =============================
```

# 3.Strong Parametersの一部を修正

```controllers/todos_controller.rb
〜省略〜
  private

    def set_todo
      @todo = Todo.find(params[:id])
    end

    def todo_params
      # params.require(:todo).permit(:title, :description)の .require(:todo)を削除
      params.permit(:title, :description)
    end
end
```




# 4.レスポンスの整形
`ActiveModel::Serializer`を使用してレスポンスを整形します。

```gemfile
gem 'active_model_serializers'
```

デフォルトではレスポンスにルートノード（`todo`の部分）が付与されるので無効にします。

```bash
{"todo":{"id":2,"title":"優先タスク","description":"とても重要なタスクです。"}}
```

```config/initializers/active_model_serializers.rb
ActiveSupport.on_load(:active_model_serializers) do
  ActiveModel::Serializer.root = false
  ActiveModel::ArraySerializer.root = false
end
```

TODOモデル用のSerializerを作成します。
レスポンスに含めたい項目のみを`attributes`に定義します。

```app/serializers/todo_serializer.rb
class TodoSerializer < ActiveModel::Serializer
  attributes :id, :title, :description
end
```

コントローラを修正します。

```app/controllers/todos_controller.rb

class TodosController < ApplicationController
  before_action :set_todo, only: [:show, :update, :destroy]

  # GET /todos
  # GET /todos.json
  def index
    @todos = Todo.all
    render json: @todos.map { |todo| TodoSerializer.new(todo)}
  end

  # GET /todos/1
  # GET /todos/1.json
  def show
    render json: TodoSerializer.new(@todo)
  end

~省略~

```

修正後の結果。

```bash
$ curl http://localhost:3000/todos/2
{"id":2,"title":"優先タスク","description":"とても重要なタスクです。"}
```


# 5.CRUDの確認

TODOの作成

```bash
$ curl -H "Content-Type:application/json; charset=utf-8" -X POST -d '{ "title":"優先タスク", "description":"とても重要なタスクです。" }' http://localhost:3000/todos
```

TODOの更新

```bash
$ curl -H "Content-Type:application/json; charset=utf-8" -X PATCH -d '{ "title":"優先タスク", "description":"かなりやばいタスクです。" }' http://localhost:3000/todos/1
```

TODOの取得

```bash
$ curl http://localhost:3000/todos/1
{"id":1,"title":"優先タスク","description":"とても重要なタスクです。"}
```

TODO一覧の取得

```bash
$ curl http://localhost:3000/todos
[{"id":1,"title":"優先タスク","description":"とても重要なタスクです。"},{"id":2,"title":"普通のタスク","description":"普通のタスクです。"}]
```

TODOの削除

```bash
$ curl http://localhost:3000/todos/1 -X DELETE
```

あとはお好きなJSフレームワークで煮るなり焼くなり。

おしまい。