第4回: Ajax (1)

2012/03/11

前回は、CoffeeScriptの関数の使い方について書きました。

今回はお待ちかね、Ajaxです。

ダブルクリックして正方形を表示させたら、その位置をデータベースに記録して永続化することにしましょう。

正方形をドラッグして位置を変更した場合の処理については、次の回で説明します。

Blockモデルの生成

まず、Blockモデルを生成します。

% rails g model block x:integer y:integer
% rake db:migrate

blocksコントローラの実装

次に、blocksコントローラを生成します。

% rails g controller blocks

config/routes.rb を修正。

Toraja::Application.routes.draw do
  root to: "top#index"
  resources :blocks, only: [ :create ]
end

app/controllers/blocks_controller.rb を修正。

class BlocksController < ApplicationController
  def create
    block = Block.create!(params[:block])
    render text: block.id
  end
end

データベースに登録された正方形を画面に表示

app/controllers/top_controller.rb を修正。

class TopController < ApplicationController
  def index
    @blocks = Block.all
  end
end

app/views/top/index.html.erb を修正。

<div id="canvas">
  <% @blocks.each do |block| %>
  <%= content_tag(:div, nil, class: "block",
      style: "left: #{block.x}px; top: #{block.y}px") %>
  <% end %>
</div>

content_tag メソッドでキャンバスの中に正方形を配置しています。

正方形の位置をデータベースに登録

ここからが本題です。

現在、app/assets/javascripts/top.js.coffee はこうなっています。

$ ->
  $("div#canvas").dblclick (e) ->
    [x, y] = positionOfNewBlock(e)
    block = $("<div class='block' style='left: #{x}px; top: #{y}px;' />").
      draggable({ containment: "parent" }).css({ position: "absolute" })
    $(e.target).append(block)

positionOfNewBlock = (e) ->
  canvas = $(e.target)
  x = e.pageX - canvas.position().left
  y = e.pageY - canvas.position().top
  [x, y]

前半部分(1-6行目)を次のように修正してください。

$ ->
  $("div#canvas").dblclick (e) ->
    [x, y] = positionOfNewBlock(e)
    $.post '/blocks', block: { x: x, y: y }, (block_id) ->
      block = $("<div class='block' style='left: #{x}px; top: #{y}px;' />").
        draggable(containment: "parent").css(position: "absolute")
      $(e.target).append(block)

  $("div.block").draggable(containment: "parent").css(position: "absolute")

最大のポイントは4行目です:

    $.post '/blocks', block: { x: x, y: y }, (block_id) ->

POSTメソッドによるAjaxリクエストを行っています。リクエスト先のURLは /blocksです。

送信されるデータは block: { x: x, y: y }。入れ子になったハッシュ(ハッシュのハッシュ)になっています。

ブラウザがこのAjaxリクエストを行うと、blocksコントローラのcreateアクションが作動して、データベースにレコードが格納されます。

createアクションは新しく登録されたBlockオブジェクトのidを文字列で返してきます。括弧の中にある変数 block_id にその文字列がセットされます。

Ajaxリクエストが成功すると -> 以下の3行が実行されます。

      block = $("<div class='block' style='left: #{x}px; top: #{y}px;' />").
        draggable(containment: "parent").css(position: "absolute")
      $(e.target).append(block)

変更前のコードの4-6行目とまったく同じです。ただし、2文字文インデントを増やしています。

もうひとつ追加されたのは、次のコードです。

  $("div.block").draggable(containment: "parent").css(position: "absolute")

データベースに登録されている正方形についてもドラッグ可能にしています。

修正が完了したら、動作確認をしましょう。ブラウザに戻り、ページを再読込してから、キャンバスの中を適宜クリックして、正方形を登録します。ページを再読込しても登録した正方形が同じ位置に表示されればOKです。

更新情報

  • ソースコードに $("div.block").draggable(containment: "parent").css(position: "absolute") を追加しました。また、「もうひとつ追加されたのは、次のコードです。」から「ドラッグ可能にしています。」までを追加しました。(2012/3/15)