Ajax によるデータの初期化

2015/06/12

前回は、Cape.JS コンポーネントとデータの関係について解説しました。

今回のテーマは、Ajax です。Rails アプリケーションの API を通じてデータベースから初期データを取得し、コンポーネントに割り当てる方法について説明します。


まずは、「Todo リスト」のタスクを記録するための tasks テーブルをデータベースに作りましょう。ターミナルで次のコマンドを実行してください。

$ bin/rails g model task

そして、テキストエディタで db/migrate/ ディレクトリの下にある _create_tasks.rb で終わる名前のファイル(「マイグレーションスクリプト」と言います)を開いて、次のように書き換えます。

class CreateTasks < ActiveRecord::Migration
  def change
    create_table :tasks do |t|
      t.string :title, null: false
      t.boolean :done, null: false, default: false

      t.timestamps null: false
    end
  end
end

tasks テーブルには、titledone という2つのカラムを持たせます。それぞれの型は、文字列型(string)、真偽値型(boolean)です。title カラムにはタスクの題名、done カラムにはタスクが完了したかどうかの真偽値を記録します。

ターミナルで次のコマンドを実行すると tasks テーブルができます。

$ bin/rake db:migrate

ターミナルには次のような結果が表示されるはずです。

== 20150612081420 CreateTasks: migrating ======================================
-- create_table(:tasks)
   -> 0.0047s
== 20150612081420 CreateTasks: migrated (0.0048s) =============================

テーブルやカラムの名前を間違えたことに気付いたら、マイグレーションスクリプトを削除して最初からやり直してください。ただし bin/rake db:migrate の代わりに bin/rake db:migrate:reset コマンドを使用してください。

シードデータ(初期データ)を投入するスクリプトを作ります。テキストエディタで db/seeds.rb を開き、コメント行(# で始まる行)をすべて削除してから、次のコードを書き入れてください。

Task.create!(title: '猫のえさを買う。', done: false)
Task.create!(title: '歯医者に行く。', done: true)
Task.create!(title: '粗大ゴミを捨てる。', done: false)
Task.create!(title: 'ブログ記事を書く。', done: false)

シードデータを投入するため、ターミナルで次のコマンドを実行します。

bin/rake db:seed

次のステップは、タスクのリストを取得するための API の作成です。

テキストエディタで config/routes.rb を開き、次のように修正します。

Rails.application.routes.draw do
  root 'top#index'

  namespace :api do
    resources :tasks, only: [ :index ]
  end
end

この結果、/api/tasks という URL パスへのアクセスを Rails アプリケーションが受け取れるようになりました。

続いて、コントローラを作ります。ターミナルで次のコマンドを実行してください。

bin/rails g controller api/tasks

app/controllers/api/tasks_controller.rb というファイルが生成されるので、それをテキストエディタで次のように修正します。

class Api::TasksController < ApplicationController
  def index
    @tasks = Task.order(id: :asc)
  end
end

そして、app/views/api/tasks ディレクトリに、新規ファイル index.jbuilder を次の内容で作成します。

json.array! @tasks, :id, :title, :done

Jbuilderは、JSON 形式のデータを作るためのテンプレートエンジンです。

API ができました。動作確認をしましょう。Rails アプリケーションを起動してから、ブラウザで http://localhost:3000/api/tasks にアクセスしてみてください。次のような文字列が表示されればOKです。

[{"id":1,"title":"猫のえさを買う。","done":false},{"id":2,"title":"歯医者に行く。","done":true},{"id":3,"title":"粗大ゴミを捨てる。","done":false},{"id":4,"title":"ブログ記事を書く。","done":false}]

Cape.JS コンポーネント側の開発に進みましょう。

テキストエディタで app/assets/javascripts/todo_list.es6 を開いてください。現在、TodoList クラスのメソッド init() は次のように定義されています。

  init() {
    this.tasks = [
      { title: "猫のえさを買う。", done: false },
      { title: "歯医者に行く。", done: true }
    ];
    this.refresh();
  }

これを次のように書き換えます。

  init() {
    $.ajax({
      type: 'GET',
      url: '/api/tasks'
    }).done(data => {
      this.tasks = data;
      this.refresh();
    });
  }

$.ajax は jQuery のメソッドです。ここでは、GET メソッドで /api/tasks にアクセスして、その結果を data というパラメータにセットしています。API から返ってくるのは文字列ですが、jQuery は JSON 形式であると判断して自動的にオブジェクトの配列に変換してくれます。つまり、Ajax コールが成功すると、this.tasks にオブジェクトの配列がセットされるのです。

this.refresh()done メソッドの内側に書いている点に注意してください。コンポーネントの init() メソッドが実行された時点ではコンポーネントのレンダリングは行われません。Ajax コールの完了時にコンポーネントのレンダリングが行われます。レンダリングのタイミングを理解することは、Cape.JS でプログラミングを行う上で非常に大切です。

では、動作確認をしましょう。ブラウザで http://localhost:3000 にアクセスし次のような画面が表示されれば成功です。

画面キャプチャ


ちょっと今回は作業内容がいつもより多かったですね。お疲れさま!

次回は、各タスクの題名の前にあるチェックボックスをクリックして、done カラムの値を変更する方法について解説します。