« RailsでWikiクローンを作る | メイン | Wiki新設 »
2005年08月29日
RailsでWikiクローンを作る 4: ページ新規作成画面の実装
入力フォームの生成
ジェネレータで生成された雛形を元に、Minki の個々の機能の実装を始めます。
まずは「ページの新規作成」です。「ページの新規作成」のアクションは、wikiコントローラに new という名前で作ることにします。 new のやるべきことは、新規ページ名の入力を求めるフォームを表示することです。 表示はビューの担当ですので、new アクションは今のところ何もしないままで放置します (ジェネレータが生成した空の定義のまま)。
一方、対応するビューのテンプレート app/views/wiki/new.rhtml は以下のように書き換えます。
<h1>新規作成</h1> <%= start_form_tag :action => 'create' %> <%= text_field 'page', 'name' %> <%= submit_tag "Create" %> <%= end_form_tag %>そして
http://localhost:3000/wiki/newにアクセスします。

フォームの開始と終了のタグは、それぞれ start_form_tag と end_form_tag で生成します。 start_form_tag の引数
:action => 'create' でフォームの submit ボタンが押されたときに実行されるアクションを指定しています(createアクションはまだ作っていません)。テキストフィールドのタグは text_field で生成します。 Railsのフォーム関連の機能は、モデルの存在を前提としたものになっていて、 上記の例の
text_field 'page', 'name'は、page というモデルの
name というカラムに格納されるべき値というような意味になります。
ちなみにこの部分は、通常時は
<input id="page_name" name="page[name]" size="30" type="text" />という HTML に展開されます。
submit ボタンは submit_tag で生成します。 submit が押されると、ユーザによってテキストフィールドに入力された値がパラメータとして start_form_tag の :action で指定したアクション(ここではcreate)に渡されます。
パラメータの受取り
では次に、その create アクションを作ります
(create は、直接対応するビューを持たないアクションです)。
app/controllers/wiki_controller.rb の create メソッドを以下のように書き換えます。
def create
@page = Page.new(params[:page])
if @page.save
redirect_to :action => 'edit', :id => @page.name
else
render :action => 'new'
end
end
アクションが呼び出されるときのパラメータは、Rails では params という属性で参照することができるようになっています。例えば、先ほどの new アクションのビューの中で、
text_field 'page', 'name'と書いたテキストフィールドの入力値は、params[:page] の :name というキーで得ることができます。
つまり、params の :page というキーで示される値 params[:page](ハッシュ)が page モデル関連の入力パラメータになっていて、その値は {:name => 入力値} というハッシュです。
この形式は、そのまま Page.new の渡せる形になっていますので、結局
@page = Page.new(params[:page])と書くことによって、
new アクションで入力された値を元に、
モデルの新しいレコードを生成することになります。
この書き方は、入力フォームで入力された値に基づき、DBテーブルに新しい行を追加する場合の常套句です。
なお、この時点では新しいレコードが Ruby 上で生成されただけで、 まだ DB には一切書き込んでいません。 DBに書き込むには、save メソッドで行います。 save は書き込みに成功したか否かを真偽値で返すので、
if @page.saveで書き込みと同時に成否を判断し、成功したら新規ページを編集するために edit アクション(後で実装)へリダイレクトし、失敗したら new の画面に戻すことになります。Railsでは、他のアクションのURLへリダイレクトするには、redirect_to というヘルパーメソッドを使います。:action => 'edit' でアクション名を指定し、:id => @page.name でIDを指定します。
save でエラーが起きた場合は、もう一度新規入力画面に戻したいわけなので、render というヘルパーメソッドを使って、'new' アクションのビューを表示します (create には、もともと対応するビューはありませんが、あったとしても
render :action => アクション名という文があると、指定したアクション名のビューが使われることになります)。
バリデーション(入力値正当性検査)
Rails では、モデルを通じて DB に値を保存する前に、その値が本来とるべき値かどうかを検査する仕組みがあります。
その検査のことをバリデーションと言います。例えば、ページの新規作成画面でページ名に何も入力しなかったら、はじくようにしなければなりませんが、その場合はモデルクラスの定義(app/models/page.rb)に以下のように書きます。
class Page < ActiveRecord::Base validates_presence_of :name endこれで、Page の name 要素が空っぽな場合にエラー(Page#saveがfalseを返す)となります。
エラーの情報はビュー側で利用することができます。 app/views/wiki/new.rhtml を以下のように変更します。
<h1>新規作成</h1> <%= error_messages_for 'page' %> <%= start_form_tag :action => 'create' %> <%= text_field 'page', 'name' %> <%= submit_tag "Create" %> <%= end_form_tag %>
<%= error_messages_for 'page' %> という行を追加しています。
error_messages_for は引数にインスタンス変数名(ここでは@page)をしています。
これで、エラーがあった場合はそのエラーが表示されるようになります。なお、error_messages_for が @page を必要とするため、newアクションでも @pageをビューに渡すようにしなければなりません。 よって、app/controllers/wiki_controller.rb の new メソッドを以下のように書き換えます。
def new
@page = Page.new
end
これで、ページの新規作成画面で、ページ名を入力せずに Create ボタンを押すと(想定通り)以下のようなエラーになります。

<div class="fieldWithErrors"> <input id="page_name" name="page[name]" size="30" type="text" value="" /> </div>スタイルシートで fieldWithErrors というクラスを適切に設定してやれば、エラーが起こった入力フォームを目立たせることができます。 例えば scaffold では背景を真っ赤にするスタイルシートが生成されます。
layout
今後、ビューのテンプレートをいくつか作っていくわけですが、ページのヘッダ、フッタ、サイドバーなど、多くのビューで共通する部分があります。
これをそれぞれのテンプレートに重複して記述していては DRY 精神に反するので、その共通部分をまとめて管理するための layout という仕組みがあります。layoutの仕組みを利用するには、決まった場所にレイアウト用テンプレートファイルを置くだけです。 決まった場所とは、コントローラの名前から、規約によって自動的に決められる場所で、 wiki コントローラのレイアウト用ファイルの置き場は app/views/layouts/wiki.rhtml です。 ここでは、以下のような内容の wiki.rhtml を作ります。
<html> <head> <title>Minki: <%= @title %></title> <%= stylesheet_link_tag '/theme/hiki/hiki.css' %> </head> <body> <a name="top"></a> <div class="main"> <h1 class="header"><%= @title %></h1> <div class="day"> <%= @content_for_layout %> </div> </div> <div class="sidebar"> </div> </body> </html>stylesheet_link_tag は、スタイルシートのタグを生成するヘルパーメソッドです。 ここではとりあえず決め打ちでパスを書いています。
インスタンス変数 @content_for_layout には各ビューのテンプレートで生成された内容が入っています。 よって
<%= @content_for_layout %> の部分は各ビューの内容で置き換えられることになります。
一方、ビューのテンプレート app/views/wiki/new.rhtml も、layout の利用にあたってちょっとだけ手直しをします。
<% @title = '新規作成' %> <div class="body"> <%= error_messages_for 'page' %> <%= start_form_tag :action => 'create' %> <%= text_field 'page', 'name' %> <%= submit_tag "Create" %> <%= end_form_tag %> </div>layoutファイル wiki.rhtml 内で使用するインスタンス変数 @title の値をセットして、h1タグの生成を wiki.rhtml 側にまかせるようにし、あと tDiary のテーマを利用するために div タグを追加しました。
あとは、public ディレクトリに Hiki から theme ディレクトリをコピーしてきて配置すれば、以下のような画面になるはずです。

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