コントローラからJavascriptの変数をセットする

Railsを使ってクイズアプリを作ってみようと考えていて、問題をロード出来たあとのロジックはHTML5Javascriptで大方書き終わっていてあとは Railsから問題をどうやって取って来ればいいんだろうっていう事が分からなかった。

REST APIを作って jsonなり XMLで取って来ればいいのかなーと考えたのが最初。けどセッション情報に基づいて取って来る問題を変えるとかすることを考えると、コントローラに対してリクエストを投げた方が多分いい。で、問題はコントローラから Javascriptの変数をセットする方法があるの?ということ。

結論: page.assignを使う

コードはこんな感じ。まずコントローラの方。page.assign "lst", aryがJavascriptの 変数lstにaryの内容をセットするところ。セットできるのは数値や文字列、Array、Hashなどが対応している。Railsの中でよしなにやってくれているらしい。

class WelcomeController < ApplicationController
  def index
  end

  def getlist
    # page.assignはArrayやHashにも対応しているっぽい
    ary = [
           ["問題1:xxxxxx", "答え: aaaaaaaaa"],
           ["問題2:xxxxxx", "答え: bbbbbbbbb"],
           ["問題3:xxxxxx", "答え: ccccccccc"],
          ]

    render :update do |page|
      page.assign "lst", ary
    end
  end
end

次はこれを扱うビュー。処理は以下の通り。

  1. loadのリンク→ loadList()呼び出し
  2. コントローラの getlist呼び出し
  3. getlistアクションの中から javascriptグローバル変数 lstに配列をセット
  4. getlistアクションの完了後に showList()呼び出し
  5. showList()の中で lstの中身を出力
<script type="text/javascript">

function showList() {
  if (lst != undefined) {
    for (var i=0; i<lst.length; i++) {
      $("lst").insert("<p>" + lst[i][0] + ", " + lst[i][1] + "</p>")
    }
  }
}

function loadList() {
  lst = undefined;
  <%= remote_function :url=>{:action=>:getlist}, :complete=>"showList();" %>
}
</script>

<%= link_to_function "load", "loadList()" %>

<div id="lst"></div>

これで、これが

こうなる

とりあえず目的は達したけど、これが正解かどうかは知らない。まあこれでクイズ出題の技術的な課題はクリアできたし、もっといい方法が分かったらそれはそのときで。