Todo ウェブアプリを作ってみよう

Worker をバージョンアップし、データベースを使用する

先ほどの Worker をバージョンアップし、Todo の登録や編集ができる Web API を追加しましょう。Todo データの管理には、Cloud SQL データベースを利用します。

Web API の仕様

追加する Web API は、次のように定義します。

Web API 機能
GET    /api/v1/todos
Todo の一覧を取得します。
POST   /api/v1/todos
Todo を登録します。
PATCH  /api/v1/todos/:id
指定 ID(:id)の Todo を更新します。
PUT    /api/v1/todos/:id
指定 ID(:id)の Todo を更新します。
DELETE /api/v1/todos/:id
指定 ID(:id)の Todo を削除します。

ステップ 2 Worker の動作イメージ画像

仕様を単純化するために、すべての Web API の戻り値は、Todo の一覧を JSON 形式で返すものとします。

{
  "data": [Todo オブジェクト, Todo オブジェクト, ... ]
}

例)
{
  "data": [{"id":1,"title":"レポート作成","completed":true},{"id":2,"title":"レポート提出","completed":false}]
}

Todo オブジェクトは、次の形式とします。

{
  "id": Todo の ID(数値),
  "title": "Todo の内容",
  "completed": Todo が完了したかどうかの Boolean 値(true か false)
}

例)
{
  "id": 2,
  "title": "レポート提出",
  "completed": false
}

登録は、Todo オブジェクトの形式で送信します。キー id は不要とします。例えば、Todo の内容が「レポート作成」で、Todo が未完了のデータを登録する場合は、次のようなります。

{
  "title": "レポート作成",
  "completed": false
}

更新は、登録と同様ですが、更新対象のキーと値のペアのみを送信します。例えば、Todo を未完了から完了に更新する場合は、次のようになります。

{
  "completed": true
}

データベース接続設定

データベース接続設定の様子

(↑クリックで拡大表示)

Todo データの管理には、Cloud SQL データベースを使用します。

Cloud SQL は、MySQL データベースをクラウド上で使用できるようにしたものです。よって、Rails アプリから Cloud SQL データベースを使用するためには、単に MySQL データベースを使用する設定とすれば良いことになります。

まず、ファイル Gemfile に、gem 'mysql2' を追加して、MySQL データベースを扱えるようにします。

source 'https://rubygems.org'

  :
(中略)
  :

gem 'mysql2'

bundle install コマンドで、mysql2 gem をインストールします。

bundle install

ファイル config/database.yml を編集し、MySQL (Cloud SQL) データベースへの接続情報を設定します。

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: <%= ENV['MYSQL_ENV_MYSQL_ROOT_PASSWORD'] %>
  host: <%= ENV['MYSQL_PORT_3306_TCP_ADDR'] %>

development:
  <<: *default
  database: todo_development

test:
  <<: *default
  database: todo_test

production:
  <<: *default
  pool: 1
  host: <%= ENV['MYSQL_HOST'] %>
  port: <%= ENV['MYSQL_PORT'] %>
  database: <%= ENV['MYSQL_DATABASE'] %>
  username: <%= ENV['MYSQL_USERNAME'] %>
  password: <%= ENV['MYSQL_PASSWORD'] %>

この例では、Rails アプリの実行モードが、development 環境および test 環境のときは、Worker 開発環境で実行する前提としています。Worker 開発環境の場合は、MYSQL_ENV_MYSQL_ROOT_PASSWORD 環境変数と MYSQL_PORT_3306_TCP_ADDR 環境変数には、それぞれ MySQL コンテナのパスワードと IP アドレスが設定されています。

実行モードが production 環境のときは、MAGELLAN で実行する前提としています。MYSQL_ で始まる環境変数には、Cloud SQL に接続するための情報が、MAGELLAN によって設定されています。

環境変数 内容
MYSQL_HOST データベースの IP アドレス
MYSQL_PORT データベースのポート番号
MYSQL_DATABASE データベース名
MYSQL_USERNAME データベースのユーザー名
MYSQL_PASSWORD 上記ユーザーのパスワード

これで、データベースに接続する準備ができました。

Web API の実装

Web API 実装の様子

(↑クリックで拡大表示)

それでは、「Web API の仕様」を実現する処理を実装しましょう。具体的には、

  • Todo データを管理するモデル
  • 各 Web API へのリクエストを処理するコントローラ
  • Todo 一覧データを JSON 形式で返すビュー

を順に実装していきます。

Todo データ管理モデルの実装

まず、Todo データを管理するモデルを実装します。Todo データは、

  • シンプルに Todo の内容を示す title(文字列)
  • Todo が完了したかどうかを示す completed(論理値)

で構成するものとします。rails generate model コマンドで、このモデルを生成します。

bundle exec rails generate model todo title:string completed:boolean

Web API コントローラの実装

続いて、Todo 管理 Web API へのリクエストを処理するコントローラを実装します。rails generate controller コマンドで、コントローラのテンプレートを生成します。コントローラ名は、Todos とします。

bundle exec rails generate controller api/v1/todos

生成された Todos コントローラのファイル app/controllers/api/v1/todos_controller.rb を次のように編集します。

class Api::V1::TodosController < ApplicationController
  # GET /api/v1/todos
  def index
    @data = Todo.all
  end

  # POST /api/v1/todos
  def create
    @todo = Todo.create(todo_params)

    @data = Todo.all
    render :index, status: :created
  end

  # PATCH /api/v1/todos/:id
  # PUT   /api/v1/todos/:id
  def update
    @todo = Todo.find(params[:id])
    @todo.update(todo_params)

    @data = Todo.all
    render :index, status: :ok
  end

  # DELETE /api/v1/todos/:id
  def destroy
    @todo = Todo.find(params[:id])
    @todo.destroy

    @data = Todo.all
    render :index, status: :ok
  end

  private

  def todo_params
    params.permit(:title, :completed)
  end
end

Todo 一覧ビューの実装

ビューは、Todo 一覧を JSON 形式で返すように、ファイル app/views/api/v1/todos/index.json.jbuilder を作成します。ファイル内容は、次のとおりです。

json.data(@data) { |todo|
  json.extract!(todo, :id, :title, :completed)
}

ファイル app/controllers/application_controller.rb を編集します。Web API を実装しているため、コメント内容に従い :exception 部分を :null_session に変更します。

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :null_session
end

ファイル config/routes.rb を編集して、ルーティングを設定します。

Rails.application.routes.draw do
  get 'hello' => 'hello#index', defaults: { format: 'json' }

  namespace :api, format: 'json' do
    namespace :v1 do
      resources :todos, :only => [:index, :create, :update, :destroy]
    end
  end
end

これで、Todo 管理 Web API ができました。

ローカルでの動作確認

ローカルでの動作確認の様子

(↑クリックで拡大表示)

ローカル(Worker 開発環境)で動作確認をします。

今回は、データベースを使用するため、サーバーを起動する前に、rake コマンドでデータベースの準備をします。

bundle exec rake db:create
bundle exec rake db:migrate

続いて、rails server コマンドで、サーバーを起動します。

bundle exec rails server --binding=0.0.0.0

別ターミナルの Worker 開発環境から curl コマンドを使って、Web API にリクエストを送ります。

Todo の登録(POST /api/v1/todos)を確認します。登録する Todo は、

  • Todo の内容(title): "todo item 1"
  • Todo の状態(completed): 未完了(false

とします。

curl -X POST -H 'Content-Type: application/json' -d '{"title": "todo item 1", "completed": false}' http://localhost:3000/api/v1/todos
{"data":[{"id":1,"title":"todo item 1","completed":false}]}

Todo の変更(PATCH /api/v1/todos/:id)を確認します。Todo の状態(completed)を未完了(false)から完了(true)に変更します。

curl -X PATCH -H 'Content-Type: application/json' -d '{"completed": true}' http://localhost:3000/api/v1/todos/1
{"data":[{"id":1,"title":"todo item 1","completed":true}]}

Todo の削除(DELETE /api/v1/todos/:id)を確認します。

curl -X DELETE http://localhost:3000/api/v1/todos/1
{"data":[]}

これで、ローカルでの動作確認は、完了です。rails server コマンドを実行しているターミナルに戻り、Ctrl + C でウェブサーバーを終了させます。

Docker イメージの再作成

Docker イメージ再作成の様子

(↑クリックで拡大表示)

バージョンアップした Rails アプリで、Worker 用の Docker イメージを再作成します。Docker イメージの再作成に用いる Dockerfile は、前回作成したものをそのまま使用します。

Docker イメージ名のタグ(バージョン)は、1.0.0 から 1.1.0 に変更します。

docker build -t username/mini-todo:1.1.0 .

Docker イメージの再作成が完了したら、再作成した Docker イメージを Docker Hub に登録します。

docker push username/mini-todo:1.1.0

再作成した Docker イメージの Docker Hub への登録が完了したら、Docker イメージの再作成は、完了です。

デプロイ

デプロイの様子

(↑クリックで拡大表示)

ここまでで、デプロイの準備が整いました。すでに MAGELLAN で動いている Worker をバージョンアップするデプロイを実施しましょう。

デプロイは、ウェブブラウザーでの作業となります。ウェブブラウザーの画面をステージ DefaultStage1 に切り替えて、以下の手順に沿って作業してください。

まずは、Cloud SQL データベースを準備します。

  1. 「DB」タブをクリックします。

    Cloud SQL の画面に切り替わります。

  2. Create Cloud SQL ボタン画像 をクリックします。

    「Cloud SQL の追加」画面が表示されます。

  3. 「Name」入力フィールドに、MiniTodo と入力し、Create ボタン画像 をクリックします。

これで、Cloud SQL データベースの準備が整いました。

続いて、Worker 情報を更新します。

  1. 「Planning」タブをクリックします。

    Worker 情報を作成・編集する画面が表示されます。

  2. 次表の内容で Worker 情報を更新します。次表で示していない項目は、変更せずそのままとしてください。

    項目名
    Image Name
    username/mini-todo:1.1.0
    Migration Command 1
    bundle exec rake db:migrate:reset db:seed
    Migration Command 2
    bundle exec rake db:migrate
  3. 更新した Worker 情報を保存します。入力内容に間違いがないことを確認して、Saveボタン画像 をクリックします。

  4. コンテナの起動ボタン画像 をクリックして、コンテナを再起動します。

これで、今回作成した Worker にバージョンアップできました。

動作確認

動作確認の様子

(↑クリックで拡大表示)

バージョンアップした Worker の動作を確認しましょう。動作の確認は、前回同様にターミナルから magellan-cli http コマンドを使います。確認手順は、「ローカルでの動作確認」で、curl コマンドで実施した内容と同等です。


Todo の登録(POST /api/v1/todos)を確認します。登録する Todo は、

  • Todo の内容(title): "todo item 1"
  • Todo の状態(completed): 未完了(false

とします。

magellan-cli http post -H '{"Content-Type": "application/json"}' -d '{"title": "todo item 1", "completed": false}' /api/v1/todos
{"data":[{"id":1,"title":"todo item 1","completed":false}]}

Todo の変更(PATCH /api/v1/todos/:id)を確認します。Todo の状態(completed)を未完了(false)から完了(true)に変更します。

magellan-cli http patch -H '{"Content-Type": "application/json"}' -d '{"completed": true}' /api/v1/todos/1
{"data":[{"id":1,"title":"todo item 1","completed":true}]}

Todo の削除(DELETE /api/v1/todos/:id)を確認します。

magellan-cli http delete /api/v1/todos/1
{"data":[]}

これで、Todo 管理 Web API の動作確認ができました。

このステップのまとめ

このステップで学んだことを簡単にまとめます。

  • MAGELLAN が提供する Cloud SQL の機能を使用すると、ボタン一発でデータベースの使用準備が整う
  • ウェブアプリと Cloud SQL の連携には、MAGELLAN が準備する環境変数を使用する
    • この環境変数は、Docker コンテナ内のアプリから参照可能
  • Worker のバージョンアップは、MAGELLAN コンソールから簡単にできる
    • Worker のイメージ名をバージョンアップ後のイメージ名に変更し、コンテナを再起動

続いて、最後のステップ「Worker にウェブビューを実装する」へ進みましょう。