バリデーションとは
バリデーション
不正なデータがデータベースに保存されないように、データをチェックする仕組みのことをバリデーションと言います。
バリデーションに引っかかった場合(不正なデータの場合)にはデータベースに保存されません。
バリデーションは図のように、モデルで設定します。
「validates」を用いてカラム名と内容を指定します。
図のように{presence: true}を用いることで、「そのカラムの値が存在するかどうか」をチェックすることができます。
class Post < ApplicationRecord
# contentカラムに対して、空の投稿を制限するバリデーションを作成してください
validates :content, {presence: true}
end
文字数のバリデーション
バリデーションlengthmaximum
バリデーションでは、値が存在しているかだけでなく、文字数もチェックすることができます。
図のように「length」を用い、{maximum: 数値}を指定することで、最大文字数を設定することができます。
class Post < ApplicationRecord
# contentカラムに対して、文字数を制限するためのバリデーションを追加してください
validates :content, {presence: true, length: {maximum: 140}}
end
バリデーションとsaveメソッド
saveメソッドの戻り値
バリデーションsave
投稿をデータベースに保存するために使ってきた「saveメソッド」は、保存に成功した場合は「true」を、バリデーションに引っかかって保存に失敗した場合は「false」を戻り値として返すようになっています。
rails consoleでsaveメソッドが真偽値を返すことを確認してみましょう。
def update
@post = Post.find_by(id: params[:id])
@post.content = params[:content]
# 保存が成功した時は投稿一覧ページ、失敗した時は編集ページにリダイレクトされるように変更してください
if @post.save
redirect_to("/posts/index")
else
redirect_to("/posts/#{@post.id}/edit")
end
end
直前の投稿を表示しよう
直前の編集内容が消えてしまう仕組み
そもそもなぜ投稿失敗時に直前の投稿内容が消えてしまうのでしょうか?
①updateアクションでは、投稿失敗時にeditアクションに転送している
②editアクションでは、データベースから編集前のデータを取得している
③フォームの初期値は、②で取得した@post.contentの内容である
以上の理由から、投稿失敗時には直前の内容ではなく編集前のデータが表示されてしまいます。
updateアクションの@postには直前の編集内容が入っているので、この@postをedit.html.erbで利用できるようにすれば、直前の編集内容を表示できるようになります。
editアクションを経由せず、updateアクションからedit.html.erbを直接表示する方法を学びましょう。
renderメソッド
render
renderメソッドを用いることで、別のアクションを経由せずに、直接ビューを表示することができます。
render("フォルダ名/ファイル名")のように表示したいビューを指定します。
renderメソッドを使うと、redirect_toメソッドを使った場合と違い、そのアクション内で定義した@変数をビューでそのまま使うことができます。
else
# renderメソッドを用いて、editアクションを経由せず、posts/edit.html.erbが表示されるようにしてください
render("posts/edit")
end
エラーメッセージを取得しよう
errorsfull_messages
saveメソッドを呼び出した際にバリデーションに失敗すると、Railsでは自動的にエラーメッセージが生成されるようになっています。@post.errors.full_messagesの中に、エラー内容が配列で入ります。
<% @post.errors.full_messages.each do |message| %>
<% end %>
サクセスメッセージを表示しよう
フラッシュ
フラッシュ
ページ上に1度だけ表示されるメッセージをフラッシュといいます。
フラッシュが表示された後、ページを更新したり、別のページに移動したりすると、フラッシュは表示されなくなります。
変数flash
flashフラッシュ
Railsではフラッシュを表示するために、特殊な変数flashが用意されています。アクションで変数flash[:notice]に文字列を代入すると、flash[:notice]をビューで使うことができます。変数flashは1度表示された後に自動で削除されるようになっています。flashはいろいろな箇所で共通で使っていくのでapplication.html.erbで表示しましょう。
if @post.save
# 変数flash[:notice]に指定されたメッセージを代入してください
flash[:notice] = “投稿を編集しました”
redirect_to(“/posts/index”)
else
render(“posts/edit”)
end
<% if flash[:notice] %>
<% end %>
def create
@post = Post.new(content: params[:content])
# 保存に成功した場合は投稿一覧ページ、保存に失敗した場合は新規投稿ページが表示されるようにif-else文を追加してください
if @post.save
redirect_to(“/posts/index”)
else
render(“posts/new”)
end
end
エラーメッセージと直前の内容の表示方法
エラーメッセージと直前の投稿内容を表示する方法は、投稿編集機能の時と同じです。図のようにコードを追加しましょう。
newアクションに@postを定義しよう
new.html.erbで変数@postを使用するようにしますが、newアクションではまだ変数@postが定義されていません。なのでnewアクション経由(localhost:3000/posts/newというURL)でアクセスしたときにエラーが出てしまいます。図のように@postにPost.newを代入しておけば、うまく動くようになります。
<% @post.errors.full_messages.each do |message| %>
<% end %>
def new
# newメソッドを用いて、Postクラスのインスタンスを作成し、変数@postに代入してください
@post = Post.new
end
新規投稿、削除機能のサクセスメッセージ
新規投稿や投稿削除に成功した場合に、サクセスメッセージを表示するようにしましょう。
def create
@post = Post.new(content: params[:content])
if @post.save
# 変数flash[:notice]に、指定されたメッセージを代入してください
flash[:notice] = “投稿を作成しました”
redirect_to(“/posts/index”)
else
render(“posts/new”)
end
end
def destroy
@post = Post.find_by(id: params[:id])
@post.destroy
# 変数flash[:notice]に、指定されたメッセージを代入してください
flash[:notice] = “投稿を削除しました”
redirect_to(“/posts/index”)
end