How to build Rails5 API + Redux ToDo Application その1

Rails5から実装されるAPI専用アプリケーションの作成手順です。

プロジェクトの生成からAPI経由でのアクセスまで試してみます。

Rails5の取得

githubからRails5を取得するため適当なディレクトリに以下のGemfileを作成します。

Gemfile

source 'https://rubygems.org'

gem 'rails', github: 'rails/rails'

Gemfileを作成後、以下のコマンドを実行し直下にrailsを取得します。

$ bundle install --path vendor/bundle

Rails5 APIアプリケーションの作成

同ディレクトリで以下のコマンドを実行します。

rails newコマンドにapiオプションを指定するとAPIのみのアプリケーションが生成されます。

$ bundle exec rails new <application-name> --api

雛形の作成

生成されたアプリケーションのディレクトリに移動し、APIの雛形となるscaffoldを生成します。

$ bin/rails g scaffold todo title completed:boolean order:integer

Running via Spring preloader in process 3582
      invoke  active_record
      create    db/migrate/20160120044614_create_todos.rb
      create    app/models/todo.rb
      invoke    test_unit
      create      test/models/todo_test.rb
      create      test/fixtures/todos.yml
      invoke  resource_route
       route    resources :todos
      invoke  scaffold_controller
      create    app/controllers/todos_controller.rb
      invoke    test_unit
      create      test/controllers/todos_controller_test.rb

雛形を作成したらDBのmigrationをします。

$ bin/rails db:migrate

== 20160120044614 CreateTodos: migrating ======================================
-- create_table(:todos)
   -> 0.0016s
== 20160120044614 CreateTodos: migrated (0.0016s) =============================

サーバーの起動

以下のコマンドを実行しサーバーを起動します。

$ bin/rails s

=> Booting Puma
=> Rails 5.0.0.beta1 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
I, [2016-01-20T13:57:13.149636 #10181]  INFO -- : Celluloid 0.17.3 is running in BACKPORTED mode. [ http://git.io/vJf3J ]
Puma 2.15.3 starting...
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://localhost:3000

※2016/01/20 サーバー起動時にactionpackがエラーを吐き出します。取り急ぎ実行したい場合は以下のファイルを編集して下さい。

config/initializers/per_form_csrf_tokens.rb

# Be sure to restart your server when you modify this file.

# Enable per-form CSRF tokens.
# 下記の行をコメントアウト
# Rails.application.config.action_controller.per_form_csrf_tokens = true

APIへのアクセス

ToDOの作成

curlを利用してJSON形式でPOSTします。

クライアント

$ curl -H "Content-Type:application/json; charset=utf-8" -X POST -d '{ "title":"単2電池を買いに行く", "order":1, "completed":false }' http://localhost:3000/todos
{"id":1,"title":"単2電池を買いに行く","completed":false,"order":1,"created_at":"2016-01-20T05:12:28.395Z","updated_at":"2016-01-20T05:12:28.395Z"}%

curl -H "Content-Type:application/json; charset=utf-8" -X POST -d '{ "title":"お土産を買いに行く", "order":1, "completed":false }' http://localhost:3000/todos
{"id":2,"title":"お土産を買いに行く","completed":false,"order":1,"created_at":"2016-01-20T05:13:50.865Z","updated_at":"2016-01-20T05:13:50.865Z"}%

サーバー

Started POST "/todos" for ::1 at 2016-01-20 14:04:17 +0900
  ActiveRecord::SchemaMigration Load (0.2ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by TodosController#create as */*
  Parameters: {"title"=>"単2電池を買いに行く", "order"=>1, "completed"=>false, "todo"=>{"title"=>"単2電池を買いに行く", "completed"=>false, "order"=>1}}
   (0.1ms)  begin transaction
  SQL (7.8ms)  INSERT INTO "todos" ("title", "completed", "order", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["title", "単2電池を買いに行く"], ["completed", false], ["order", 1], ["created_at", 2016-01-20 05:04:17 UTC], ["updated_at", 2016-01-20 05:04:17 UTC]]
   (1.1ms)  commit transaction
Completed 201 Created in 32ms (Views: 1.5ms | ActiveRecord: 9.8ms)

Started POST "/todos" for ::1 at 2016-01-20 14:13:50 +0900
Processing by TodosController#create as */*
  Parameters: {"title"=>"お土産を買いに行く", "order"=>1, "completed"=>false, "todo"=>{"title"=>"お土産を買いに行く", "completed"=>false, "order"=>1}}
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "todos" ("title", "completed", "order", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["title", "お土産を買いに行く"], ["completed", false], ["order", 1], ["created_at", 2016-01-20 05:13:50 UTC], ["updated_at", 2016-01-20 05:13:50 UTC]]
   (0.7ms)  commit transaction
Completed 201 Created in 4ms (Views: 0.6ms | ActiveRecord: 1.2ms)

ToDO一覧の取得

クライアント

$ curl http://localhost:3000/todos
[{"id":1,"title":"単2電池を買いに行く","completed":false,"order":1,"created_at":"2016-01-20T05:12:28.395Z","updated_at":"2016-01-20T05:12:28.395Z"},{"id":2,"title":"お土産を買いに行く","completed":false,"order":1,"created_at":"2016-01-20T05:13:50.865Z","updated_at":"2016-01-20T05:13:50.865Z"}]%

サーバー

Started GET "/todos" for ::1 at 2016-01-20 14:15:23 +0900
Processing by TodosController#index as */*
  Todo Load (0.2ms)  SELECT "todos".* FROM "todos"
Completed 200 OK in 3ms (Views: 2.1ms | ActiveRecord: 0.2ms)

ToDOの更新

クライアント

curl -H "Content-Type:application/json; charset=utf-8" -X PATCH -d '{ "completed":true }' http://localhost:3000/todos/1
{"id":1,"completed":true,"title":"単2電池を買いに行く","order":1,"created_at":"2016-01-20T05:12:28.395Z","updated_at":"2016-01-20T05:17:05.151Z"}%

サーバー

Started PATCH "/todos/1" for ::1 at 2016-01-20 14:17:05 +0900
Processing by TodosController#update as */*
  Parameters: {"completed"=>true, "id"=>"1", "todo"=>{"completed"=>true}}
  Todo Load (0.3ms)  SELECT  "todos".* FROM "todos" WHERE "todos"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  SQL (0.4ms)  UPDATE "todos" SET "completed" = ?, "updated_at" = ? WHERE "todos"."id" = ?  [["completed", true], ["updated_at", 2016-01-20 05:17:05 UTC], ["id", 1]]
   (1.0ms)  commit transaction
Completed 200 OK in 75ms (Views: 0.5ms | ActiveRecord: 1.8ms)