ちょっと忙しかったので

気分転換に Rails を進めてみた。行儀としてどうか?というのもあるのだが、ブックマークのリンクをクリックしたときに、onClickイベントを拾って、サーバにクリックされた事を(非同期で)送り、ブラウザ上は、平然と別ウィンドウを開くような画面を書いてみた。Ajax(というか、非同期通信が可能なXMLHttpRequestかな)って、見た目に表れないバックグラウンドで何かできちゃうから、もし一般にやるなら、こんなことやりますって書いとかないとまずいのかな。見た目も変わらないし。ソース見ちゃえば解かるし、外部向けのサービスじゃやらないだろうな。


チュートリアルなので、色々組み合わせて動作を確認したい。なので、XMLHttpRequestを使ってみることと、リンクのクリックをカウントする方法を実装してみることにする。
まずは、今までのテーブルを少し修正。last_updatedを削除して、created_dateというのを同じ役割で追加。あとは、access_rateというカラムも追加して、クリックされたような場合の上位をここに記録。rateってかいてあるが、時間経過と共に、減らしていけばいいかなと...。まぁ、この辺は色々あるだろうけど、お手軽な感じで。cronで定期的に減らしていけば良いかなと。

ALTER TABLE bookmarks DROP COLUMN last_updated;
ALTER TABLE bookmarks ADD COLUMN created_date DATETIME;
ALTER TABLE bookmarks ADD COLUMN access_rate FLOAT DEFAULT 1.0;

すぱっと、作り直しちゃったので、日付がnullになっている。とりあえず、現在時刻を入れる。

UPDATE bookmarks set access_rate = now();


app/controllers/bookmarks_controller.rb の last_updated を created_date に置換しておく。あとは、クリックされた時に受け取る為のメソッドが必要になる。こんなのを用意してみた。

 def accessed
   @bookmark = Bookmark.find(params[:id])
   @bookmark.access_rate += 1
   @bookmark.save
 end

このページが呼ばれた時の結果画面も用意する。これは、app/views/bookmarks/accessed.rhtml
というようなファイルを用意して、次のような手抜きな内容にした。結局、XMLHttpRequestから呼ばれて捨てられるので、今はあまり凝る必要ないし。

 <h1>Accessed bookmark</h1>
 
 Increased access_rate for <%= @bookmark.title %>.

そして、JavaScriptとして次のようなのを public/javascripts/accessed.js
として用意しておく。

function call_accessed(id) {
    var xmlhttp = createXmlHttp();
    if (xmlhttp != null) {
        xmlhttp.onreadystatechange = function handleHttpEvent() {
            if (xmlhttp.readyState == 4) {
                if (xmlhttp.status == 200) {
                    // ignore the response data because
                    // to call is important here.
                } else {
                    // some connection error happened.
                }
            }
        }
        xmlhttp.open("GET", "/bookmarks/accessed/" + id, true);
        xmlhttp.send(null);
    } else {
        // cannot use ajax.
    }
}

function createXmlHttp(){
    if (window.ActiveXObject) {
        return new ActiveXObject("Microsoft.XMLHTTP");
    } else if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
    } else {
        return null;
    }
}

これをViewでどうやって取り込んだら良いのか解からなかったので、調べてみたら javascript_include_tag というのがあるそうな。ということで、それらしい全体のレイアウト用ファイルを探してみたら、 app/views/layouts/bookmarks.rhtml これっぽいので、headに次の行を追加する。

<%= javascript_include_tag 'accessed' %>

これで、JavaScriptが参照できるようになった。

あとは、一覧が表示されるViewに、次のようにonClickハンドラを追加すれば良さそうだ。

<td><%= link_to bookmark.title, bookmark["url"] ,
 {"onClick" => "call_accessed(#{bookmark['id']});",
  "target" => "_blank"}%></td>

これで、listにアクセスし、登録しているURLをクリックした後、DBを見るとaccess_rateの値は増えているみたい。あとは、時間経過と共に減らしていけば、最近よく見た上位のものがうえに来るようになるかなと。この仕掛けも、一人で使う分にはたいして面白くないけど、複数だと面白いかもしれないなぁ。

あとは、登録時にコンテンツを引っ張ってきて、簡易検索/更新確認 ぐらいができると面白いかも。