ページネーション

2008/12/17

前回は、トップページが表示できたところで終わりました。

単体テストは通るでしょうか。

> rake test:units
(省略)
/usr/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:428:in
 `load_missing_constant': Expected /home/kuroda/hgrepos/books/kiso_rails/cd-rom/chapter9/
app/helpers/mobile/blog_entries_helper.rb to define Mobile::BlogEntriesHelper (LoadError)
(省略)

あれれ、通りませんね。問題の app/helpers/mobile/blog_entries_helper.rb を見ると次のようになっています。

module Mobile::BlogsHelper
end

読者の皆様にまたしても謝らなければなりません。CD-ROM 付属のソースコードにミスがありました。次のように修正してください。本当に済みません。

module Mobile::BlogEntriesHelper
end

これで、単体テストは通ります。

次に、機能テストです。

> rake test:functionals
(省略)
92 tests, 235 assertions, 4 failures, 13 errors
(省略)

ああ、失敗です。

ざっとエラーメッセージを見ると、ページネーション関連でエラーが出ています。

ページネーションは、Rails 2.0 からフレームワーク本体から分離されてプラグインになりました。そのままでは動きません。

Rails 2.0 が出た当時は、classic_pagination プラグインをインストールせよ、と言われていましたが、インストールを試みると…

> ruby script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination
svn: ホスト 'errtheblog.com' に接続できません: Connection refused

と拒絶されてしまいます。もはや提供されていないようです。

代替品(性能的には classic_pagination よりも良い)の mislav-will_paginate を使うことにします。

> gem sources -a http://gems.github.com
http://gems.github.com added to sources
> sudo gem install mislav-will_paginate
Successfully installed mislav-will_paginate-2.3.6
1 gem installed
Installing ri documentation for mislav-will_paginate-2.3.6...
Installing RDoc documentation for mislav-will_paginate-2.3.6...

読者の方からの指摘を受けて、インストール手順に

> gem sources -a http://gems.github.com

を追加しました。mislav-will_paginate プラグインは、標準の gem リポジトリではなく GitHub を通じて配布されています。

config/environment.rb に次のような記述を追加します。。

  config.gem 'mislav-will_paginate', :lib => 'will_paginate'

追加する位置は、

Rails::Initializer.run do |config|
  ...
end

の内側です。

では、ひとつずつ潰していきましょう。手始めに、main コントローラから。

> ruby test/functional/main_controller_test.rb

大量の警告とエラーメッセージが出ました。まず、次のエラーを何とかしましょう。

NameError: uninitialized constant MainController::Paginator

オリジナルはこうなっています:

(省略)
  # 私たちの活動
  def activities
    page = (params[:page] || 1).to_i
    @activities, count = 
      Article.current_articles('activities', ARTICLES_PER_PAGE, page)
    @activities_pages =
      Paginator.new(self, count, ARTICLES_PER_PAGE, page)
    @number_of_members = Member.count
  end
  
  # ニュース
  def news
    page = (params[:page] || 1).to_i
    @news, count = 
      Article.current_articles('news', ARTICLES_PER_PAGE, page)
    @news_pages =
      Paginator.new(self, count, ARTICLES_PER_PAGE, page)
  end
(省略)

これを、このように書き換えます:

(省略)
  # 私たちの活動
  def activities
    @activities =
      Article.current_articles('activities').paginate(:page => params[:page], :per_page => ARTICLES_PER_PAGE)
    @number_of_members = Member.count
  end
  
  # ニュース
  def news
    @news =
      Article.current_articles('news').paginate(:page => params[:page], :per_page => ARTICLES_PER_PAGE)
  end
(省略)

次に、テンプレート activities.rhtmlnews.rhtml を書き換えます。
オリジナルはこうなっています:

(省略)
<% if @activities_pages.page_count > 1 -%>
<div class="pagination">
  <%= my_pagination_links @activities_pages, :window_size => 9 %>
</div>
<% end -%>
(省略)

activities.rhtml を次のように書き換えます:

(省略)
<%= will_paginate @activities, :previous_label => '前へ', :next_label => '次へ', :inner_window => 2 %>
(省略)

news.rhtml を次のように書き換えます:

(省略)
<%= will_paginate @news, :previous_label => '前へ', :next_label => '次へ', :inner_window => 2 %>
(省略)

我々が作った pagination_links プラグインと mislav-will_paginate プラグインでは、1ページ目へのリンクの書き方が異なるので、テストを書き換えます。

test/functional/main_controller_test.rb を開き、a[href=/main/news] をすべて a[href=/main/news?page=1] に置換してください。

これで main_controller_test.rb は通ります。

ただし、次のような警告が大量に表示されます。

DEPRECATION WARNING: truncate takes an option hash instead of separate length and omission arguments.

Rails 2.2 から truncate メソッドの引数の取り方が変わっています。

Rails 2.1 までは truncate(text, length, omission) でしたが、Rails 2.2 以降は truncate(text, *args) となり、文字列の長さは :length オプションで渡すことになりました。

      <%= my_format(truncate(a.body, 20)) %></li>

を、次のように修正します。

      <%= my_format(truncate(a.body, :length => 20)) %></li>

再度、すべての機能テストを実行します。

> rake test:functionals
(省略)
92 tests, 278 assertions, 4 failures, 8 errors
(省略)

エラーの数が 13 から 8 に減りました。

疲れました。本日はここまで。