このページの内容は以下のリポジトリに1日遅れで反映されます(記事執筆前に前日分をコミットしています)。
https://github.com/hkob/hkob_blog
はじめに
Rails Tips の 59 回目です。昨日は、new による追加画面を作成しました。この form の結果を受けて記事を作成する create を実装しましょう。
7.3 記事を1件作成する
こちらも先にテストを記述しましょう。create は成功する場合と失敗する場合の二通りのテストが必要です。まだ shared_example に登録されていないものはこちらで紹介してあります。
- オブジェクト数が…? shared_example: 小林研 Rails Tips (13)
- リダイレクト確認 shared_example : 小林研 Rails Tips (24)
- Notice メッセージ確認 shared_example : 小林研 Rails Tips (25)
- Alert メッセージ確認 shared_example : 小林研 Rails Tips (26)
let!(:attrs) { object.attributes } describe "POST #create" do before { object.destroy } subject { -> { post articles_path, params: {article: attrs} } } let(:return_path) { article_path(Article.order(created_at: :desc).first) } context "正しいパラメータに対して" do it_behaves_like "レスポンスコード確認", 302 it_behaves_like "オブジェクトが1増えるか?", Article it_behaves_like "リダイレクト確認" it_behaves_like "Notice メッセージ確認", "記事を登録しました。" end context "不正なパラメータに対して" do before { attrs["title"] = "" } it_behaves_like "レスポンスコード確認", 422 it_behaves_like "オブジェクト数が変化しない?", Article it_behaves_like "Alert メッセージ確認", "記事の登録に失敗しました。" end end
create action は Strong parameter の article_params を呼び出し、new で作成した記事を保存します。保存に成功した場合、作成した記事のページにリダイレクトします。逆に失敗した場合には、new を再描画します。
def create @article = Article.new(article_params) if @article.save redirect_to @article, notice: notice_message(Article) else flash.now[:alert] = alert_message Article render :new, status: :unprocessable_entity end end private def article_params params.require(:article).permit(:title, :body) end
ここで notice_message とalert_message のための翻訳テキストは config/localtes/views/ja.yml
に以下のように設定します。
flash: create: notice: "%{obj}を登録しました。" alert: "%{obj}の登録に失敗しました。" update: notice: "%{obj}を更新しました。" alert: "%{obj}の更新に失敗しました。" edit: alert: "%{obj}を編集する権限がありません。" destroy: notice: "%{obj}を削除しました。" alert: "%{obj}を削除する権限がありません。" show: alert: "%{obj}を表示する権限がありません。" copy: notice: "%{obj}を一括コピーしました。" duplicate: notice: "%{obj}を複製しました。" edit_status: create: "編集を開始します。" update: "編集状態を解除しました。" remove_all: notice: "%{obj}を全て削除しました。" append_all: notice: "%{obj}を一括登録しました。" update_all: notice: "%{obj}を一括更新しました。" permission_error: alert: "ページを表示する権限がありません。"
あとは application_controller.rb に alert_message と notice_message の実装を追加するだけです。
# @param [Class] klass 表示するクラス # @return [String] 表示する alert message # @see https://hkob.hatenablog.com/entry/2023/12/17/050000 def alert_message(klass, acn = nil) I18n.t "flash.#{acn || action_name}.alert", **{obj: klass.model_name.human} end # @param [Class] klass 表示するクラス # @return [String] 表示する notice message # @see https://hkob.hatenablog.com/entry/2023/12/17/050000 def notice_message(klass, acn = nil) I18n.t "flash.#{acn || action_name}.notice", **{obj: klass.model_name.human} end helper_method :notice_message
これで create のテストおよび実装が完了しました。POST #create の RSpec の結果は以下のようになっています。無事に全てのテストが通過しています。
POST #create 正しいパラメータに対して behaves like レスポンスコード確認 レスポンスのステータスが 302 であること behaves like オブジェクトが1増えるか? Article.count が 1 つ増えること behaves like リダイレクト確認 is expected to redirect to "/articles/655299031" behaves like Notice メッセージ確認 notice に「記事を登録しました。」が出力されること 不正なパラメータに対して behaves like レスポンスコード確認 レスポンスのステータスが 422 であること behaves like オブジェクト数が変化しない? Article.count が変化しないこと behaves like Alert メッセージ確認 alert に「記事の登録に失敗しました。」が出力されること
おわりに
create が完了したので、新しい記事が投稿できるようになりました。edit はほとんど new と変わらないので、明日は update まで実装します。