====== メールフォーム ====== ===== 概要 ===== フォームに入力した内容をメールで送るプログラムです。webサイトのお問い合わせ受付画面などに利用できます。 {{:samples:mailform_index.png|}} ===== パス ===== examples_controller ===== 構成ファイル ===== ^ ファイル名 ^ 説明 ^ | index.rb | コントローラ使用のためのエントリポイント。 | | mailform/_contact.html | お問い合わせ受付画面の部分テンプレート | | mailform/_thanks.html | お問い合わせを受付完了画面の部分テンプレート | | mailform/layout.html | 各画面共通のレイアウトを定義するための部分テンプレート | | mailform/main.rb | コントローラ | | mailform/styles/ | テンプレートから読み込む | ===== 使用ライブラリ ===== ^ ライブラリ名 ^ 説明 ^ | al_controller | コントローラクラス。コントローラアプローチで開発を行うために必要。| | al_template | テンプレートマネージャ。レスポンスとしてwebブラウザに送信するためのHTMLを生成します。 | | al_form | フォームマネージャ。ブラウザから送信されたフォームデータの処理などを行います | ===== 詳細 ===== ===== コントローラ(hello/main.rb)でのフォームの処理 ===== ==== AlFormオブジェクトとAlWidgetオブジェクト ==== Aloneでフォームを表示したりクライアントから送信されたデータを受け取ったりするには、AlFormオブジェクトとAlWidgetオブジェクトを作成します。AlFormは一つのフォームに対応し、フォーム内のテキストボックスやセレクトボックスなどに対応するAlWidgetのサブクラスのオブジェクトを複数保持します。AloneではAlWidgetであらかじめ定義されたフォーム要素以外は受け取ることができません。これによりプログラマが想定していないデータを送り込まれることを防ぐことができ、セキュリティを高めることができます。 メールフォームサンプルでは、make_contact_formメソッドでこれらのオブジェクトを作成しています。 def make_contact_form form = AlForm.new form.set_widgets( AlText.new('name', :label => 'お名前', :required => true, :tag_attr => {:size => 20}), AlMail.new('mail', :label => 'メールアドレス', :required => true, :tag_attr => {:size => 40}), AlText.new('company', :label => '会社・団体名', :required => false, :tag_attr => {:size => 40}), AlText.new('phone', :label => '電話番号', :required => false, :tag_attr => {:size => 14}), AlText.new('subject', :label => '件名', :required => true, :tag_attr => {:size => 40}), AlTextArea.new('message', :label => '内容', :required => true, :cols => 40, :rows => 8), AlSubmit.new('submit', :value => '問い合わせ送信') ) return form end ==== フォームの表示 ==== フォームを構成するHTMLをビューで生成するには、
タグの内側でAlForm#make_tagメソッドを呼び出して各ウィジェットに対応するタグを生成します。 コントローラのaction_indexメソッド内では、まずmain.rb内で定義されているmake_contact_formメソッドを呼び出してAlFormオブジェクトとAlwidgetオブジェクトを生成しています。 @form = make_contact_form その後、AlTemplate#runを呼び出し、ビューの処理を行っています。 AlTemplate.run 'layout.html' 実際のフォームの生成は、layout.htmlから呼び出される部分テンプレート_contact.htmlが行っています。_contact.html内のフォーム関係部分を以下に示します。 <%= unless @form.validation_messages.empty? html = "
    " @form.validation_messages.each do |k, v| html << "
  • #{v}
  • " end html << "
" end html %>
<%= @form.make_tag(:name) %> 例: 亜論 太郎
<%= @form.make_tag(:mail) %> alone@example.com
お問い合わせに対する回答を差し上げるメールアドレスです。
<%= @form.make_tag(:company) %> 例: イグザンプルコーポレーション
差し支えなければご記入ください。
<%= @form.make_tag(:phone) %> 例: 0853-00-0000
差し支えなければご記入ください。
<%= @form.make_tag(:subject) %>
<%= @form.make_tag(:message) %>
<%= @form.make_tag(:submit) %>
=== ウィジェットに対応するタグの生成 === AlForm#make_tagメソッドをウィジェット名を表すシンボルをつけて呼び出すことにより、ウィジェットに対応するHTMLタグが表示されます。 === エラーの表示 === フォーム送信後、コントローラ内でAlForm#validationを実行した際にバリデーションエラーが発生した場合、メールフォームサンプルではエラーメッセージとともに再度フォームを表示します。エラーメッセージの表示は、バリデーションエラーのメッセージが格納される配列AlForm.validation_messagesが空でなければエラーメッセージのHTMLを生成することで実現しています。 ==== GET/POSTメソッドでの処理分岐 ==== 本サンプルでは、1個のアクション action_index のみで、フォームの表示および送信されたフォームの処理(メール送信と受付画面の表示)を行っています。これは、HTTPメソッドがGETかPOSTかによって処理を分岐することにより実現しています。 HTTPメソッド種別の判別は、Alform#fetch_requestメソッドで行っています。fetch_requestメソッドは、HTTPリクエストに含まれるフォーム情報(POSTメソッドの場合)またはQUERY_STRING(GETメソッドの場合)を取得・解析します。本メソッドの引数に"POST"を指定して呼び出すとHTTPメソッドがPOSTでない場合はフォームの解析を行わずfalseを返すため、HTTPリクエストの判別に利用できます。 if @form.fetch_request('POST') && @form.validate then @order_detail = mail_body(@form) send_mail(:from => MAIL_FROM, :to => RCPT_TO, :subject => MAIL_SUBJECT, :reply_to => @form.values[:mail], :body => @order_detail) @part_template = '_thanks.html' else @part_template = '_contact.html' end ==== フォーム要素の値の取得 ==== フォームで送信された値を取得するにはAlForm#fetch_requestメソッドを使用します。このメソッドはフォームで送信された内容を解析し、AlFormオブジェクトにあらかじめ設定されていたAlWidgetオブジェクトに解析したフォーム要素の値をセットします。 なお、fetch_requestメソッドを呼び出した直後はウィジェット内部に値はセットされていますが、まだウィジェットから値を取り出すことはできません。値を取り出すためにはAlForm#validateメソッドを呼び出してバリデーションを行わなければなりません。値を使用する前にバリデーションが強制されることにより、プログラム内で参照できるフォームの値は妥当性検査を行ったものであることが保証され、プログラムのセキュリティが高まります。 AlForm#validateメソッドが呼び出されると、AlFormが保持しているすべてのAlWidgetオブジェクトに対してvalidateメソッドが呼び出されます。AlWidget#validateメソッドは各ウィジェットに組み込まれたデフォルトのバリデーションのほか、必須入力項目のチェック、:filter属性で指定されたバリデーションなどを行います。 メールフォームサンプルでAlForm#fetch_requestメソッドとAlForm#validateメソッドを呼び出しているコードを示します。通常、AlForm#fetch_requestとAlForm#validateは以下の例のように連続して呼び出します。 if @form.fetch_request('POST') && @form.validate then ===== 部分テンプレート ===== メールフォームサンプルでは、フォーム画面とフォーム送信後に表示される受付完了画面でレイアウトを共有するために、部分テンプレートを利用しています。部分テンプレートにより大半のHTMLを共有することができるため、重複した記述を排除してビューの記述量を減らしたりメンテナンスしやすくしたり等の効果が得られます。 両画面で共通して使われるlayout.htmlを示します。 お問い合わせフォーム
お問い合わせ
<% include @part_template %>
headタグ、ヘッダ表示部、フッタ表示など共通部分の記述はこのファイルで行っています。<% include @part_template %>を呼び出すことにより、インスタンス変数@part_templateに設定された部分テンプレートファイルを読み込みます。 インスタンス変数@part_templateはコントローラ内で設定されています。@part_templateを設定している箇所を示します。 if @form.fetch_request('POST') && @form.validate then @order_detail = mail_body(@form) send_mail(:from => MAIL_FROM, :to => RCPT_TO, :subject => MAIL_SUBJECT, :reply_to => @form.values[:mail], :body => @order_detail) @part_template = '_thanks.html' else @part_template = '_contact.html' end