at posts/single.html

Rails に(再)挑戦 3日目 - 更新順序で並び替え

昨日はビューの見栄えを変えるところまで。 今日はロジック(モデルとコントローラ)に手を加えてみよう。 今の状況だと、各ページは id 順(つまり古い順)に並んでいる。 これを、更新した順(新しい順)に表示されるようにする。

更新順に並べるために、まずは Page クラスへ更新時刻とついでに作成時刻を追加する。

マイグレーション

migration の機能を使って、データベースの pages テーブルに更新時刻と作成時刻を追加する。 マイグレーションファイルの雛形は、 script/generate で生成できる。

$ script/generate migration AddUpdatedToPage
      exists  db/migrate
      create  db/migrate/002_add_updated_to_page.rb

pages テーブルに対して、生成時刻 (created) と更新時刻 (updated) のカラムを追加する。 検索速度を速くするために、それぞれにはインデックスを張るようにしている。

$ vi db/migrate/002_add_updated_to_page.rb
class AddUpdatedToPage < ActiveRecord::Migration
  def self.up
    add_column :pages, :created, :time
    add_index  :pages, :created
    add_column :pages, :updated, :time
    add_index  :pages, :updated
  end

  def self.down
    remove_column :pages, :created
    remove_column :pages, :updated
  end
end

rake コマンドを使って、データベースのスキーマを修正する。

$ rake migrate
(in /home/machu/work/misc/rails/rn)
== AddUpdatedToPage: migrating ================================================
-- add_column(:pages, :created, :time)
   -> 0.0275s
-- add_index(:pages, :created)
   -> 0.0084s
-- add_column(:pages, :updated, :time)
   -> 0.0300s
-- add_index(:pages, :updated)
   -> 0.0040s
== AddUpdatedToPage: migrated (0.0734s) =======================================

コントローラの修正

データベースの準備ができたので、NoteController に手を加える。

一覧表示 (list) にて、更新時刻の新しい順に並び替えるようにオプション(:order => 'updated DESC')を指定する。 それから、新規作成 (create) と更新 (update) の時に、生成時刻と更新時刻と設定するようにした。

$ vi app/controllers/note_controller.rb

class NoteController < ApplicationController
  def list
    @page_pages, @pages = paginate :pages,
                                   :per_page => 10, :order => 'updated DESC'
  end

  def create
    @page = Page.new(params[:page])
    @page.created = Time.now
    @page.updated = Time.now
    if @page.save
      # 中略
    end
  end

  def update
    @page = Page.find(params[:id])
    @page.updated = Time.now
    if @page.update_attributes(params[:page])
      # 中略
    end
  end
end

ビューの修正

せっかく生成時刻と更新時刻を記録するようにしたので、画面にも表示するようにビューを修正する。 具体的には Page の共通ビュー (_page.rhtml) に下記の2行を追加している。 このビューは一覧表示 (list) と個別表示 (show) で共通に使われるようにしているので、一箇所を変えれば一覧表示と個別表示の両方に反映される。 共通化しておいて良かった。

$ vi app/views/note/_page.rhtml

  created: <%= page.created.strftime('%Y-%m-%d %H:%M') if page.created %>
  updated: <%= page.updated.strftime('%Y-%m-%d %H:%M') if page.updated %>

データの移行

これまでに作られたページには生成時刻も更新時刻も含まれていない。 そこで、コンソール (script/console) を使って、既存のデータに生成時刻と更新時刻を設定する。 迷ったけど、とりあえず現在時刻を両者に設定することにした。

$ script/console
Loading development environment.
>> Page.find(:all).each do |page|
?> page.created = Time.now
>> page.updated = Time.now
>> page.save
>> end

これで、新規に作ったページや更新したページが、上に表示されるようになった。

関連する日記