Rails+JSフレームワークでリアルタイム掲示板を作成してみる(AngularJS編)


あー、俺もそろそろ最近のjsフレームワーク覚えなきゃ・・と思い始めてから早3プロジェクツ。自分で作りたいWebサービスがあるのだが、どのフレームワークを使用するのがベターなのか正直よく分かんない。有名どころののAngularJS, Backbone.js, Ember.jsのいずれかがよいのだろうと思うが、それぞれ一体どんな特徴があるのだろうか。というわけで今回は、各フレームワークを使用して実際に簡単なアプリを作成してみることにした。まずはAngularJS、お前からだ!

こんなアプリを作る

掲示板アプリを作ってみようと思う。単なる掲示板だとつまらないので、twitter風に自動で投稿が表示されるようにしてみた。

環境

  • Ruby on Rails 4.1
  • AngularJS 1.3

セットアップ

全てはGemfileから始まる。ポイントはRails Assetsを利用している点。Javascript用のパッケージマネージャBowerと、ruby用のパッケージマネージャBunlderの橋渡しをしてくれている。要するに、Bower用のJavascriptライブラリをラップしたgemを提供してくれるということだ。

Gemfileを記述したら、通常通り bundle installを実行する。localhost:3000を開くと、Welcome aboardが表示されるはずだ。

次にAngularJSを使用する準備にかかる。 app/assets/javascripts/application.jsを編集する。

jqueryやturbolinksは使用しないので削除した。3行目で指定しているboard_sapmpleというのはこれから作成するファイルだ。(このファイル内でAngularJSのセットアップをするのでrequire_treeよりも上に記述しておかなければならない。)

トークンの設定をしているのはコメントに記載している通り、認証を突破するためだ。railsのコントローラ側でスキップする手もあるが、今回はこのように対応した。(※IE9以下では動かない)

続いて、アプリケーションで使用するレイアウトファイルを作成しておく。

シンプルこの上ないレイアウトだが、重要な記述が2行目にある。 ng-app="BoardSample"という部分で、AngularJSが自動起動するディレクティブを指定する。先程セットアップしたBoardSampleアプリケーションを指定している。

このあたりで、AngularJSがうまく設定できているか確認してみる。まずはコントローラを作成して・・・

ルートURLをこのpagesコントローラに設定しておく。

http://localhost:3000にアクセスするとページがレンダリングされるはずなので、JavascriptコンソールでAngularJSのバージョンを確認してみよう。 angular.version.fullと入力してみよう。

バージョン


バージョンが表示されれば、正しくAngularJSがセットアップできているということだ。

step1. 投稿を表示する

それでは掲示板作りに入っていこう。投稿モデル(Post)を生成する。

rake db:migrateも忘れずに。生成した投稿モデルにRESTインターフェースを実装してあげよう。

とりあえず今はindexメソッドだけ実装した。ちゃんとJSONが取得できるか試す前に、テストデータを登録しておこう。 db/seeds.rbを編集する。

編集が終わったら、 rake db:seedを実行してからhttp://localhost:3000/posts/にアクセスしてみよう。

json
文句なしにJSONが取得できた。(ちなみに私はJSONViewというChrome拡張を使用してます)

ひとまずこれでrails側はうまく動いているので、クライアント側の実装に入る。この投稿RESTモデルにマッピングしたangular-resourceというのを実装することから始めよう。 app/assets/javascripts/angular/services/post.js.coffeeというファイルを作成する(場所は任意)。

/postがマッピングするRESTインターフェースのURLである。これだけで投稿モデルに対するCRUDインターフェースが用意できた。それでは投稿を表示する画面・コントローラを作成することにしよう。まずは home.html.erbを修正する。

ng-controller="PostsCtrl"でコントローラを指定している。これから作成するAngularJSのコントローラだ。2行目では ng-repeat="post in posts"と記述し、投稿を繰り返し表示するようにしている。その他詳細は公式サイトのドキュメントを漁れば分かると思う。

ではいよいよコントローラを作成する。いよいよという程のコード量ではないのだが。

1行目でPostリソースをDI注入しており、3行目の Post.query()にてGET /post.jsonが走るようになっている。 $scope.postsが先程のビューにデータバインドされるというわけだ。http://localhost:3000にアクセスしてみると・・・

投稿全表示
うまく表示できた! ほんのすこしだけカッコをつけよう。

white-space: pre; を指定しておけば、投稿本文に改行(\n)が含まれている場合、実際に改行して表示てくれるので楽チンだ。「そんなの <%= simple_format ... %>とすればいいじゃないか」と思ったあなたは、まだrailsのクセが抜けてない。今我々が記述しているのは『あっち側』じゃなくて、『こっち側』だ。

step2. 投稿できるようにする

掲示板らしくするために、投稿する機能を実装しよう。まずは投稿フォームがなければ何も始まらない。

ng-submitでフォームのsubmit時に呼び出すコントローラ内のメソッドを指定する。 ng-modelはコントローラからデータバインドされるオブジェクト名だ。修正後の posts_ctrl.js.coffeeを見れば一目瞭然だろう。

普段はほとんど書かないコメントを書きまくったので、先程のビューとの関連が分かると思う。そういえばrails側のPostsController#createメソッドを実装していないことを思い出したぞ。

投稿機能の実装はこれにて完了。ブラウザで動作を確認してみる。

投稿
投稿が即座に反映され、リロードしても元に戻っていなければ成功だ!

step3. 未読投稿を自動取得する

だんだんとそれっぽくなってきたとはいえ、この掲示板は仕様上の大問題がある。最初に画面を表示してからリロードするまで、他人の投稿が一切反映されないくせに、自分の投稿は反映させるということ。実際の投稿の並びとは異なる可能性があるのに。。。チュートリアルとはいえ、さすがにこんなダサい仕様はアレルギーものなので、定期的に未読の投稿を取得するという今風な仕様に変更してみることに。

posts_ctrl.js.coffeeを思いっきり修正する。

1行目に $intervalという引数を追加しているが、こいつで定期的に未読投稿をサーバから取得するようにしている。ちなみにJavascript標準のsetTimeout()は使用しない方がよい。AngularJSによってバインドされたデータの変更が検知できないので(このあたりについては、angularjs timeout apply といったワードでググってみるとよい)。未読分の取得の方法だが、現在表示している投稿の最大idを利用して検索をかけるようにしている。

ではその検索に対応するため、rails側を編集することにしよう。思いっきり手を抜くためransackを利用することにした。

bundle installしてwebrickを再起動するのを忘れずに。準備が整ったらブラウザを2つ並べて片方で何か投稿してみよう。他方の掲示板にも自動的に未読分が表示されるはず!

step4. アニメーションさせる

機能としてはこれで完成だが、未読分の投稿が追記されたことに気づきにくいという難点がある。AngularJSはアニメーションにもつおいらしいので、調子に乗って未読分をハイライトさせてみよう。

AngularJSではアニメーションは別パッケージになっているので、Gemfileを修正する必要がある。

また、application.jsとboard_sample.js.coffeeの修正も必要だ。

ではアニメーション機能を実装する・・・といっても実はたいしてやることはない。というのもAngularJSは非常に気の利くいいヤツでして、リストにエントリーを追加する際に専用のCSSを付加してくれているらしい。すなわち、次のようなcssを用意するだけで・・・

完成
ピカっと輝くようになった。完成!!

完成品はこちらからダウンロードできます

所感

他のフレームワークをまだ試してないので比較はできないものの、AngularJSの雰囲気がある程度つかめた。

  • RESTインターフェースと親和性が高い
  • アニメーションやらバリデーションまで、オールインワン
  • ng-appやng-controllerのおかげでディレクティブ単位のコンポーネント作成なんかが簡単っぽい
  • railsと同様、Fatコントローラになりやすそうな予感

個人的な開発にも手軽に使えそうだなーと分かったところで、寝ることにしよう。。あぁ長かった・・・

次回はEmber.jsにチャレンジする予定。

参考リンク

関連する記事


コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください