「RailsによるアジャイルWebアプリケーション開発」23章読了
Web2.0と題して、Prototype、Script.aculo.us、RJSテンプレートが取り上げられています。
Ajaxでdiv要素の更新
ページ中のpタグで囲ったところだけ、Ajaxで更新するというサンプルです。
ここでは、四つの方法で実現してみました。
- ハイパーリンクをクリックすると更新される
- フォームボタンをクリックすると更新される
- divで括られたテキストをクリックすると更新される(イベントハンドラ)
- 5秒置きに自動的に更新される(疑似プッシュ技術的な)
さっそく解説をば。
まずは、prototype.jsが必要になるので、JavaScriptライブラリの取り込みを行うため、レイアウトファイルを修正します。
app/views/layouts/products.html.erb
<head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Products: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %> <!-- add --> <%= javascript_include_tag :defaults %> </head>
headタグ内に追加しました。
:defaultsにすると、Prototype、Script.aculo.us、application.jsが取り込まれますが、個別に取り込むことも可能です。
次にコントローラ。
app/controllers/products_controller.rb
def ajaxtest end def ajaxtest_partial @dateTime = Time.now render(:partial => 'ajaxtest') end
Ajaxテスト用ページを表示するアクションajaxtestと、Ajaxリクエストに対してレスポンスを返すajaxtest_partialのアクションを定義しました。
次にビュー。
まずは、Ajaxレスポンスを描画するビューを作ります。
app/views/products/_ajaxtest.html.erb
<%= @dateTime %>
コントローラで取得した日時を、ただ表示しているだけですね。
次に、Ajaxレスポンスを取り込む本体のビューです。
app/views/products/ajaxtest.html.erb
<h3>Ajaxのテスト</h3> <!-- ajaxリクエストを行うハイパーリンク --> <%= link_to_remote "日時を更新リンク", :url => {:action => :ajaxtest_partial}, :update => 'datetime1' %> <!-- ajaxリクエストを行うフォームボタン --> <% form_remote_tag :url => {:action => :ajaxtest_partial}, :update => 'datetime1' do %> <%= submit_tag "日時を更新ボタン" %> <% end %> <!-- ajaxリクエストを行うHTML要素 --> <div onclick = "<%= remote_function(:update => 'datetime1', :url => {:action => :ajaxtest_partial}) %>"> 日時を更新テキスト(クリックしてね) </div> <!-- n秒置きに自動更新 --> <%= periodically_call_remote :url => {:action => :ajaxtest_partial}, :update => 'datetime1', :frequency => 5 %> <p id='datetime1'/>
ちと長いですが、冒頭で書いた4つの部分に分かれていることが分かれば、理解は容易かと思います。
でもって、
http://localhost:3000/products/ajaxtest/1
へアクセス。
すると、こんなページが表示されます。
どれかをクリック or 5秒間待つことで、ページ下部に現在の日時が表示されます。
簡単にできちゃいますね。
オートコンプリート
Google Suggest(http://www.google.com/webhp?hl=ja&complete=1)的な検索ボックスが実現できる機能らしいです。
とりあえずRails2.xではプラグインになったようなので、プラグインをインストールしてみる。
taka@taka-desktop:~/test$ ruby script/plugin install auto_complete + ./README + ./Rakefile + ./init.rb + ./lib/auto_complete.rb + ./lib/auto_complete_macros_helper.rb + ./test/auto_complete_test.rb
で、書籍の内容は役たたずになったようなので、このインストールされたREADMEを参考にコントローラとビューを作ってみる。
まずは、コントローラ。
app/controllers/products_controller.rb
auto_complete_for :post, :autocomplete_favorite_language def autocomplete_demo end def auto_complete_for_post_user_favorite_language puts(params[:post][:user_favorite_language]) render(:text=>'<ul><li>Ruby</li><li>Java</li><li>Haskell</li><li>C#</li></ul>') end
テキストフィールドに入れられた内容は、params[:post][:user_favorite_language]で取得できますが、
ここでは簡略のため、固定のリストを返すようにしています。
次にビュー。
app/views/products/autocomplete_demo.html.erb
<p><label for="user_favorite_language">お気に入りの言語</label><br/> <%= text_field_with_auto_complete :post, :user_favorite_language %>
text_field_with_auto_completeでオートコンプリート用テキストフィールドを生成しています。
で、
http://localhost:3000/products/autocomplete_demo/1
にアクセス。
と、NoMethodErrorで怒られる。
しばらく悩んだのち、
http://koress.jp/2007/08/ruby_on_rails.html
のサイトで、WEBrickを再起動する必要があることを知りました。。
で、再起動でとりあえずNoMethodErrorは解決。
次に、フォームが表示されたものの、
一向にオートコンプリートされない。
POSTだからダメなのかと思い、GETにしてみても同じくダメ。
試しにPOSTで直接アクセスしてみたらどうなるのかと思い、
こんなHTMLを書いてみることに。
public/test.html
<html> <form method="POST" action="/products/auto_complete_for_post_user_favorite_langu age"> <input type = "submit" value = "push"> </form>
で、http://localhost:3000/test.htmlにアクセスし、pushボタンをクリック。
すると、
ActionController::InvalidAuthenticityToken in ProductsController#auto_complete_for_post_user_favorite_language
が出てました。
これは、
http://brass.to/blog/rails_2_0_auto_complete.html
でも書かれている問題で、このページからリンクされている、
http://d.hatena.ne.jp/jakei/20080305/1204764230
のサイトのパッチを当てることで回避できました。(念のためWEBrickは再起動)
ちなみにですが、WEBrickのコンソールログにステータスコード422ってのが表示されてて、
なんだろうと思ってHTTP/1.1の仕様(RFC2616; http://www.ietf.org/rfc/rfc2616.txt)を見たのですが載ってませんでした。
これはWebDAVのために拡張されたもので、
RFC4918; http://www.ietf.org/rfc/rfc4918.txt
の11.2章に載ってますね。