AtomPubな何かを作ってみよう その7 〜実装編 Part.06「各リソース間を接続しよう」〜
今回は各リソース間の接続性のお話です。
接続性は大事
RESTfulWebサービスにとって、接続性(Connectedness)は重要な要素の一つです。どのリソースとどのリソースが繋がっているのかが明示的に示されていないと、どこからも接続されていない孤立したリソースができてしまったりします。
…という事は重々承知していたものの、本シリーズのここまでの記事で作成したリソースは残念ながら全く接続されていません…。
このままではRESTfulWebサービスとしてはよろしくないので、それぞれのリソースを接続する事を考える事にしましょう。
リンクの設計を考える
まずは、どんなリンクが必要になるか考えてみましょう。
今のところ、名付けて.ね〜むの各リソースは次のようなリンクを持っています。
実線はlinkタグで既にリンク済みのもの、破線は前回、サービス文書によって関係性を紐付けたものです。
サービス文書による紐付けは、クライアントが必ずしも対応してくれるとは限らない為、多少弱い紐付けと言えるので、きちんとlinkタグでリンクするようにしましょう。
また、子リソースがどのリソースの子供なのか分かるように、子→親の関係もリンクするようにします。これで、次のようなリンクが作られる事になります。
コードとしてはViewにリンク要素を追加していく形になります。
例として、meaningsリソースから子リソースへのリンクの場合は次のように、"app/views/meanings/entry.rxml"に追加します。
entry.link(:rel => 'related', :href => meaning_url(@meaning.name)+'/comments') entry.link(:rel => 'related', :href => meaning_url(@meaning.name)+'/namedwords')
逆に、namedwordsリソースからmeaningsリソースのような子リソースから親リソースへのリンクの場合は次のように、"app/views/namedwords/feed.rxml"に追加します。
feed.link(:rel => 'related', :href => meaning_url(@meaning.name))
これを、図中の赤い線全てについて実施していけば、各リソース間が接続されたWebサービスになります。
ページングを実装する
更に、ついでなので各Feedのリソースにページングのリンクも入れるようにしましょう。
Railsのページングに関しては、以下の記事と、この記事からの一連の追記辺りを参考にさせて頂きました。
→Ruby on Rails 2.0.1に対応 - idesaku blog
まずは、ページングのプラグインをインストール。
$ gem sources -a http://gems.github.com/ $ gem install mislav-will_paginate
あとは、environment.rbの末尾にrequireを追加すれば準備はオッケー。
require 'will_paginate'
続いて、Controllerでfindで記事の一覧を取得していたところを、paginateで取得するように変更します。
#@meanings = Meaning.find(:all, :conditions => condition, :order => 'updated desc', :limit => 20) @meanings = Meaning.paginate(:conditions => condition, :order => 'updated desc', :page => params[:page], :per_page => 20)
最後に、Viewで最初・最後・前・次のリンクを出力するようにすれば完成です。
feed.link(:rel => 'self', :href => meanings_url) feed.link(:rel => 'first', :href => meanings_url+'?page=1') if ( @meanings.size > 0 ) feed.link(:rel => 'prev', :href => meanings_url+'?page='+@meanings.previous_page.to_s) if ( @meanings.previous_page ) feed.link(:rel => 'next', :href => meanings_url+'?page='+@meanings.next_page.to_s) if ( @meanings.next_page ) feed.link(:rel => 'last', :href => meanings_url+'?page='+@meanings.total_pages.to_s) if ( @meanings.size > 0 )
一応、それぞれ必要な時だけ出力するように、if文をくっつけています。非常にあっさり実装できて素晴らしいですね。
ちなみに、色々なサイトを見て調べながらやっていたんですが、will_paginateの実装がバージョンによって違うのか、各値の取得方法が何種類か見つかって、どれが正しいのか分からなくて困りました…。
総ページ数の取得が、サイトによって"total_page"だったり"page_count"だったり…。結局のところ、今回インストールしたwill_paginateは2.3.8で、このバージョンだと上記のように、"total_pages"で総ページ数が取得できました。*1
という訳で、今回は各リソース間の接続についてのお話でした。
次回は?
次回は、ユーザリソースを新たに追加して、認証・認可に関する辺りに入っていこうかと思います。