記事を1件作成する: 小林研 Rails Tips (58)

このページの内容は以下のリポジトリに1日遅れで反映されます(記事執筆前に前日分をコミットしています)。

https://github.com/hkob/hkob_blog

はじめに

Rails Tips の 58 回目です。show による記事を1件表示することができたので、new で新規作成ページを作成するところまでを実装しましょう。

Rails をはじめよう - Railsガイド

7.1 記事を1件表示する

こちらも先にテストを記述しましょう。new は記事の作成というタイトルと表のタイトルが表示されていることを確認する程度でいいと思います。

  describe "GET #new" do
    subject { -> { get new_article_path } }
    it_behaves_like "レスポンスコード確認", 200
    it_behaves_like "描画結果に文字列が含まれている?", %w[記事作成 タイトル 本文]
  end

new action は Article の new で一つオブジェクトを作成する。この時点ではまだデータベースには登録されていません。

  def new
    @article = Article.new
  end

new で仮作成したコンテンツを app/views/articles/new.html.haml で描画します。

- content_for :title do
  - @page_title = t ".title"

= render "form"

今回は先に翻訳文字列を追加しておきます。

    new:
      title: 記事作成
      link_title: 追加

app/views/articles/_form.html.haml は以下のようになります。form_label_and_errorform_label_and_error ヘルパー : 小林研 Rails Tips (41) で紹介したものです。

= form_with model: @article do |f|
  %table
    %thead
      %tr
        %th 項目
        %th 内容
    %tbody
      - %i[title body].each do |attr|
        %tr
          %td= form_label_and_error f, @article, attr
          %td
            - case attr
            - when :title
              = f.text_field attr
            - else
              = f.text_area attr, rows: 10, cols: 80
      %tr
        %td{colspan: 2}= f.submit

form_label_and_error のテストは今回の article を使うと以下のようになります。実装は 41 日目のものそのままで動作します。

    describe "form_label_and_error" do
      let(:article) { articles :can_delete }
      let(:lbl) { "<label for=\"article_title\">タイトル</label>" }
      let(:err) { "<span class=\"error_message\">タイトルを入力してください</span>" }
      it "form_label_and_error で適切なラベルが設定できること" do
        form_with model: article do |f|
          expect(helper.form_label_and_error(f, article,  :title)).to(
            eq "<div>#{lbl}</div>")
          expect(helper.form_label_and_error(f, article, :title, add_text: "add_text")).to(
            eq "<div>#{lbl}<span>add_text</span></div>")
          article.title = nil
          article.save
          expect(helper.form_label_and_error(f, article,  :title)).to(
            eq "<div><div class=\"field_with_errors\">#{lbl}</div><br></br>#{err}</div>")
        end
      end
    end

最後に index.html に new へのリンクを追加しておきます。

- content_for :title do
  - @page_title = t ".title"

%table
  %thead
    = labels Article, %w[title], add_control: true
  %tbody
    - @articles.each do |article|
      %tr
        %td= article.title
        %td= lotfp article_path(article)
    %tr
      %td= lotfp new_article_path

おわりに

form_label_and_error が正しく動いているかどうかは、実際に create を使った時に正しくエラーが表示されるかにかかっています。こちらは明日確認しましょう。