« RailsでWikiクローンを作る | メイン | Wiki新設 »
2005年08月31日
RailsでWikiクローンを作る 6: ページ表示
LoadingModule
後回しになっていた show アクションを実装します。
show は、Wiki のページを表示するアクションです。
つまり wiki ソースをパースして、HTML に変換することになります。この部分は Hiki のソースを利用させてもらい、以下の二つのファイルを作りました (ソースは後で公開します)。
- parser_default.rb
- Hikiの style/default/parser.rbをほぼそのまま流用。 Hiki::Parser_default というクラスを定義している。 HikiのWiki文法で書かれた文字列を構文解析してトークン列に変換する。
- formatter_default.rb
- Hikiの style/default/html_formatter.rbを元に、 minki 用に InterWikiName やプラグインなどの機能削って手直ししたもの。 Hiki::Formatter_default というクラスを定義している。 トークン列を HTML に変換する。
問題は、これらのファイルをどこに配置すれば良いか、です。 lib あるいは vendor というディレクトリに置いておいて、どこかで require するという手もありますが、ここでは Rails の LoadingModule という機能を使います (LoadingModule について、詳しくは http://wota.jp/ac/?date=20050810#p01 等を参照してください)。
app/controllers/hiki というディレクトリを作って、そこに parser_default.rb と formatter_default.rb を入れておくと、Rails アプリ中で Hiki::Parser_default や Hiki::Formatter_default というクラスを使おうとすると、自動的にそれらのファイルを load してくれます。
そして、app/controllers/wiki_controller.rb の show メソッドを以下のように書き換えます。
def show
@page = Page.find_by_name params[:id]
@title = (@page.title and !@page.title.empty?) ? @page.title : @page.name
conf = Struct.new(:use_plugin, :use_wikiname).new(false, false)
parser = Hiki::Parser_default.new conf
tokens = parser.parse @page.content
formatter = Hiki::Formatter_default.new tokens, self, conf
@body = Hiki::Formatter_default.apply_tdiary_theme(formatter.to_s)
render :text => @body, :layout => true
end
@page = Page.find_by_name params[:id] で、params[:id]で示されるページ名を検索して、該当する行を @page に代入します
(該当する行がなかった場合の処理は後ほど追加します)。
そして、@page.title に何か入っていればそれを、なければ @page.name を @title に代入します。次の
conf = ... の部分は、まだ管理画面を作っていないので Struct でダミーの conf オブジェクトを生成しています。
後程、管理画面を作って、conf には設定情報オブジェクトが入るようになる予定です。
parser = Hiki::Parser_default.new conf でHikiパーサオブジェクトを作り、tokens = parser.parse @page.contentで、@page.content に入っている Wiki ソースをトークン列に分解します。
そして、Hiki::Formatter_default でトークン列をHTML文字列に変換して @body に代入しています。最後の
render :text => @body, :layout => trueは、@body の内容でビューをレンダリングするという意味で、HTMLタグも一切エスケープされずにそのまま出力されます。
その場合テンプレートは使われませんが、:layout => true と指定しているので layout は利用します。
動作確認
では、今まで実装した部分の動作確認をしてみます。
まずhttp://localhost:3000/wiki/new にアクセスしてページの新規作成画面を出します。
そして、何か適当なページ名(ここではSandBox)を入力してページを作成します。



flash
さて、show アクションに存在しないページ名をつけて呼び出したらどうなるでしょうか?
例えば http://localhost:3000/wiki/show/hogehoge にアクセスすると以下のようになってしまいます。

- 呼び出しパラメータのページ名をDBで検索し、見つかったらその編集フォーム画面を表示する
- 指定ページが見つからなかったら、見つからない旨を表示しつつ新規作成画面を表示する
Railsにはこのような用途に使う flash という機構があります。 flashの実体はハッシュのようなもので、アクションの処理に関する各種データ、例えばメッセージなどの文字列を入れておくことができます。 flashに入れたデータはセッションという機構を使って次のリクエストだけに引き継がれ、その後は自動的に消されます。
その flash 機構を利用して show メソッドを以下のように書き換えます。
def show
@page = Page.find_by_name params[:id]
if @page
@title = (@page.title and !@page.title.empty?) ? @page.title : @page.name
conf = Struct.new(:use_plugin, :use_wikiname).new(false, false)
parser = Hiki::Parser_default.new conf
tokens = parser.parse @page.content
formatter = Hiki::Formatter_default.new tokens, self, conf
@body = Hiki::Formatter_default.apply_tdiary_theme(formatter.to_s)
render :text => @body, :layout => true
else
flash[:notice] = '指定のページは存在しません。ぜひ作成してください:-)'
redirect_to :action => 'new', :id => params[:id]
end
end
前回の show に比べて、Page.find_by_name でページが見つからなかった場合の処理(else節)を加えています。
flash[:notice] の部分で、flash に「指定のページは存在しません」というメッセージを格納しています。
そして、new アクションへリダイレクトしていますが、flash のデータはそのアクションに引き継がれます。一方、new のテンプレート app/views/wiki/new.rhtml は、flash にメッセージが格納されていれば、それを表示する必要があるので、以下のように修正します。
<% @title = '新規作成' %> <div class="body"> <%if flash[:notice] %> <p style="color: green"><%= flash[:notice] %></p> <% end %> <%= error_messages_for 'page' %> <%= start_form_tag :action => 'create' %> <%= text_field 'page', 'name' %> <%= submit_tag "Create" %> <%= end_form_tag %> </div>追加したのは
<%if flash[:notice] %> <p style="color: green"><%= flash[:notice] %></p> <% end %>の3行で、flash[:notice] に値が入っていればそれを表示するようにしています。
それでは動作確認です。http://localhost:3000/wiki/show/hogehoge (存在しないページ名)にアクセスすると、

しかし、このままでは入力フォームが空っぽでちょっと不親切です。 入力フォームに指定したページ名を入れるため、 app/controllers/wiki_controller.rb の new メソッドに一行追加して修正します。
def new
@page = Page.new
@page.name = params[:id] if params[:id]
end
ID が指定されていれば、それを@page.nameに代入しているだけです。
これで、http://localhost:3000/wiki/show/hogehoge にアクセスすると、

投稿者 tam : 2005年08月31日 09:18
トラックバック
このエントリーのトラックバックURL:
http://tam.qmix.org/mt3/mt-tb.cgi/13