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


はじめに

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

環境

Ruby 2.2.3
Rails 4.2.6

1.プロジェクトの準備

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

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

2.TODOリソースの作成

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

$ 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のマイグレーションをします。

$ 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を使用してレスポンスを整形します。

gem 'active_model_serializers'

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

{"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

~省略~

修正後の結果。

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

5.CRUDの確認

TODOの作成

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

TODOの更新

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

TODOの取得

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

TODO一覧の取得

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

TODOの削除

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

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

おしまい。