はじめに
Rails Tips の 42 回目です。昨日、フォームのラベルとエラーを表示する form_label_and_error
を紹介しました。今回は、ラベル行を作成する際に利用する form_labels_and_errors
ヘルパーを紹介します。
form_label_and_error の使い方
昨日説明した form_label_and_error
の実際の利用例を示します。これは、シラバスの編集画面では書籍を追加する場合のフォームです。各行にラベルの項目列とフォームの内容列があります。このラベルの描画部分に form_label_and_error
を使っていました。キーでループすることでラベル部分が共通化できているだけでなく、text_field
の入力部分も else で共通化できています。
= form_with model: @new_textbook, url: create_textbook_teacher_syllabus_syllabus_textbooks_path do |f| %table.bordered %thead %tr %th 項目 %th 内容 %tbody - add_texts = {yomi: "(ひらがなと全角スペースのみ)", isbn: "(検定教科書以外はハイフンなし13桁かハイフンあり17桁必須)"} - %i[name yomi author price kentei isbn publisher_id].each do |key| %tr %th= form_label_and_error f, @new_textbook, key, add_text: add_texts[key] %td - case key - when :price = f.number_field key - when :kentei = f.collection_radio_buttons :kentei, [%w[検定教科書 true], %w[通常書籍 false]], :last, :first - when :publisher_id = @new_textbook.publisher.name - else = f.text_field key, size: 20, autofocus: key == :name
form_labels_and_errors の使い方
一方で出版社のページでは書籍一覧のページの表の中で編集フォームが存在しています。この形もフォームも多いので、ヘッダ部分は form_label_and_error
のみのループを実行する必要があります。同じようなループをあちこちに書くのは莫迦らしいので、専用の form_lables_and_errors
というヘルパーを用意しました。key
だった部分がキーの配列になり、add_text
の部分が key
で引くことができるハッシュになっているだけです。
= form_with model: [:teacher, @textbook] do |f| %table.bordered - keys = %i[name yomi author isbn kentei price] %thead = form_labels_and_errors f, @textbook, keys, add_texts: {yomi: "(ひらがなと全角スペースのみ)", isbn: "(検定教科書以外はハイフンなし13桁かハイフンあり17桁必須)"} %tbody %tr - keys.each do |key| %td - case key - when :kentei = f.collection_radio_buttons key, [%w[検定教科書 true], %w[通常書籍 false]], :last, :first - when :price = f.number_field key - else = f.text_field key, autofocus: key == :name %tr %td.warning{colspan: 6} = f.hidden_field :publisher_id = f.hidden_field :url = f.submit
form_labels_and_errors のテスト
テストは以下のようになります。ひとつのパターンしかテストしていませんが、form_label_and_error
の方でさまざまなパターンをテストしているので問題ないでしょう。上の例では使っていませんが、labels と同様に add_control: true
をつけることで制御列を追加できます。
it "form_labels_and_errors で適切なラベルが複数設定できること" do form_with model: year do |f| expect(helper.form_labels_and_errors(f, year, %i[year default_year], add_texts: { default_year: "add_text", }, add_control: true)).to( eq [ "<tr><th><div>#{lbl}</div></th>", "<th><div><label for=\"year_default_year\">デフォルト年度</label>", "<span>add_text</span></div></th>", "<th>制御</th></tr>" ].join("") ) end end
form_labels_and_errors の実装
こちらは単に form_label_and_error
をループしているだけなので、実装は難しくないと思います。
# @param [form] form # @param [Object] model # @param [<Array<Symbol>] keys # @param [Hash] add_texts def form_labels_and_errors(form, model, keys, add_texts: {}, add_control: false) content_tag :tr do keys.each do |key| concat content_tag(:th) { form_label_and_error(form, model, key, add_text: add_texts[key]) } end if add_control concat content_tag(:th) { I18n.t "common.control" } end end end
おわりに
form_label_and_error
と form_labels_and_errors
を利用することで、縦型・横型のどちらの form でもラベル描画が楽に記述できるようになりました。