#実装したいこと
・新規投稿および編集の失敗の際、エラーメッセージを表示させる。
・成功の際には遷移先の画面にフラッシュメッセージを表示させる。
エラーメッセージのイメージはこんな感じ。
あくまでイメージなので、説明の際に用いるコードは別物。(こちらは以前作成したアプリのスクショ)
#エラーメッセージの実装
投稿用のモデルはPostモデル
とし、Userモデル
と1対多の想定で説明を進める。
1.モデルにバリデーションをかける
class Post < ApplicationRecord
belongs_to :user
#空の投稿を不可にする
validates :title, presence: true
validates :content, presence: true
end
2.アクションに処理内容を追加
投稿失敗の際の画面表示の方法として、redirect_to
によるアクションを介する画面遷移をしてしまうと、作成していたデータは全て白紙の状態にされてしまう。
そのため投稿データの作成に失敗した場合には、render
メソッドを用いてアクションを介さず新規投稿画面の表示のみを行う。
def create
@post = Post.new(post_params)
@post.save
redirect_to posts_path
end
↓ 以下のように編集
def create
@post = Post.new(post_params)
if @post.save
#保存が成功した場合は一覧ページに遷移
redirect_to posts_path
else
#失敗した場合は直前の画面を表示
render "new"
end
end
updateアクションにも同様の編集を行う
##3.エラーメッセージファイルの作成
###補足説明
バリデーションエラーで保存に失敗した場合、Railsのデフォルトの仕様により自動的にエラーメッセージが生成され、インスタンス変数.errors.full_messages
の中にエラー内容が配列で入ることとなる。
このことはrails console
で不適正なデータを作成して確認してみると実感として理解しやすい。
$ rails c
:
[1] pry(main)> post = Post.new(title:"", content:"")
[2] pry(main)> post.errors.full_messages => [] #保存失敗の前は空の配列の状態
[3] pry(main)> post.save => false
[4] pry(main)> post.errors.full_messages => ["Titleを入力してください", "Contentを入力してください"] #保存に失敗した時点で、配列にエラーメッセージが含まれる
このように生成されたエラーメッセージを、タグを用いて投稿フォーム内に埋め込む。
今回はエラー表示のコードを部分テンプレートとして用意し、フォーム内にrenderで埋め込む。
renderで埋め込むエラーメッセージのファイルがこちら。
<% if model.errors.any? %>
<div class="alert alert-warning">
<ul>
<% model.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
ちなみに上記コードのようにmodel.errors.full_messages
とすることで、どのモデルにも対応できるようになる。
もちろん部分テンプレートとしてではなく、各モデルの新規投稿フォームに直接記述するのであれば、@post.errors.full_messages
のような書き方でも問題ない。
4.部分テンプレート(パーシャル)をフォーム内に挿入する
:
<%= form_with model:@post, local:true do |f|%>
<%= render 'layouts/error_messages', model: f.object %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="form-group">
<%= f.label :content %>
<%= f.text_area :content %>
</div>
<%= f.submit "投稿する" %>
<% end %>
:
2行目のこの部分で、部分テンプレート内で使用している変数model
にフォームのオブジェクト(f.object
)を渡している。
<%= render 'layouts/error_messages', model: f.object %>
#フラッシュメッセージの実装
1.作成が成功した際のフラッシュメッセージの挿入
今までの手順で作成が失敗した場合のエラーメッセージの表示ができるようになったので、今度は作成成功の際のフラッシュメッセージを表示させるようにする。
データ更新、データ削除の際のフラッシュメッセージも同様に記述する。
:
def create
@post = Post.new(post_params)
if @post.save
flash[:notice] = "投稿を作成しました"
redirect_to posts_path
else
render "new"
end
end
:
def update
@post = Post.find(params[:id])
if @post.update(post_params)
flash[:notice] = "投稿を更新しました"
redirect_to post_path(@post)
else
render "edit"
end
end
:
def destroy
@post = Post.find(params[:id])
@post.destroy
flash[:notice] = "投稿を削除しました"
redirect_to posts_path
end
:
2.ビューにフラッシュメッセージのコードを挿入
ビューファイルにflash[:notice]
を埋め込む。
基本的にどの画面でも対応できるようにするため、application.html.erb
にコードを記述するのが望ましい。
<body>
<header>
:
</header>
<% if flash[:notice] %>
<div class="flash">
<%= flash[:notice] %>
</div>
<% end %>
<%= yield %>
</body>
以上の手順でフラッシュメッセージの実装が完了。
ちなみにフラッシュメッセージにはflash[:notice]
の他にflash.now[:notice]
など記述方法がいくつかあり、機能が異なるので用途に応じて使い分けることをお勧めする。
参考記事:flashとflash.nowの違いを検証してみた
記載内容に間違いがあった場合はご指摘頂けると嬉しいです。
ご連絡お待ちしております。