バリデーション
不正なデータがデータベースに保存されないように、データをチェックする仕組みのことをバリデーションと言う
バリデーションに引っかかった場合(不正なデータの場合)にはデータベースに保存されない
バリデーションの書き方(例:空の投稿を制限する)
モデルにて「validates」を用いてカラム名と内容を指定する。
《models/post.rb》
validates :content, {presence: true} 検証する内容
検証するカラム名
- {presence: true}を用いることで、「そのカラムの値が存在するかどうか」をチェックすることができる
バリデーションを確認する
《ターミナル》
$ rails console
post = Post.new(content: “”)
post.save
- 空の投稿を防ぐバリデーションを設定すると、空の投稿に対してsaveメソッドを用いて保存しようとしても、保存が失敗するようになる
文字数のバリデーション
バリデーションでは、値が存在しているかだけでなく、文字数もチェックすることができる
《models/post.rb》
validates :content,{length: {maximum: 140}}
- 「length」を用い、{maximum: 数値}を指定することで、最大文字数を設定できる
検証する内容を複数指定する
《models/post.rb》
validates :content,{presence: true,length: {maximum: 140}}
- コンマで区切ることで、複数指定できる
バリデーションとsaveメソッド
バリデーションに引っかかったら、もう一度入力フォームに戻るようにする。
そのためにまず、バリデーションの結果によって、 save メソッドが異なる結果になることを学ぶ
saveメソッドの戻り値
投稿をデータベースに保存するために使ってきた「saveメソッド」は、保存に成功した場合は「true」を、バリデーションに引っかかって保存に失敗した場合は「false」を戻り値として返すようになっている。
《ターミナルで確認》
$ rails console
post = Post.new(content: “”)
post.save
=> false ←保存失敗時
post.content = “我が名はアシタカ”
post.save
=> true ← 保存成功時
バリデーションの結果で表示するページを変える
新規投稿や投稿編集フォームで、投稿が失敗した時には、再びフォームを表示するようにする
save メソッドが、保存出来たら「true」、保存できなかったら「false」を返すことを利用する
表示するページを切り替える
投稿を保存できなかった場合は投稿一覧ページの代わりに投稿編集ページに転送するようにする
《posts_controller.rb》
def update
if @post.save ←保存できた場合
redirect_to(“/posts/index”)
else ← 保存失敗した場合
redirect_to(“/post/#{@post.id}/edit”)
end
end
- 「saveメソッド」が、保存できたかどうかで「true」または「false」を返すことを利用する
- リスト
直前の投稿内容を表示する
直前の編集内容が消えてしまう仕組み
以上の理由から、投稿失敗時には直前の内容ではなく編集前のデータが表示されてしまう
【理由1】updateアクションでは、投稿失敗時にeditアクションに転送している
《posts_controller.rb》
def update
redirect_to(“posts/#{@post.id/edit}”)
end
【理由2】editアクションでは、データベースから編集前のデータを取得している
《posts_controller.rb》
def edit
@post = Post.find_by(…)
end
【理由3】フォームの初期値は、②で取得した@post.contentの内容である
《edit.html.erb》
<textarea>
<%= @post.content %>
</textarea>
直前の投稿内容を表示する仕組み
updateアクションの@postには直前の編集内容が入っているので、この@postをedit.html.erbで利用できるようにすれば、直前の編集内容を表示できるようになる。
《posts_controller.rb》
def update
@post = Post.find_by(di: params[:id])
@post.content = params[:content] ←直前の内容が入っている
end
- editアクションを経由せずに、updateアクションからedit.html.erbを直接表示したい
renderメソッド
renderメソッドを用いることで、別のアクションを経由せずに、直接ビューを表示することができる
《posts_controller.rb》
def update
@post = Post.find_by(di: params[:id])
@post.content = params[:content] ←直前の内容が入っている
render(“posts/edit”)
end
《posts/edit.html.erb》
<textarea>
<%= @post.content %>
</textarea>
- render(“フォルダ名/ファイル名”)のように表示したいビューを指定する
- redirect_toメソッドを使った場合と違い、そのアクション内で定義した@変数をビューでそのまま使うことができる
- ※redirect_toはURLを指定して「redirect_to(URL)」のように書く
エラーメッセージを表示する
エラーメッセージを取得する
saveメソッドを呼び出した際にバリデーションに失敗すると、Railsでは自動的にエラーメッセージが生成されるようになっている。@post.errors.full_messagesの中に、エラー内容が配列で入る
《ターミナル》
post = Post.new(content=””)
post.errors.full_messages => []
post.save => false
post.errors.full_messages => [“コメントを入力してください”]
- リスト
- リスト
エラーメッセージの表示
edit.html.erbのフォームの上で、each文を用いてエラー文を1つずつ表示
《edit.html.erb》
<%= @post.errors.full_messages.each do |message| %> ←エラーメッセージの配列
<%= message %>
<% end %>
サクセスメッセージを表示する
サクセスメッセージは、投稿した直後だけ表示して、それ以降は表示しないようにする
フラッシュ
ページ上に1度だけ表示されるメッセージをフラッシュという。
フラッシュが表示された後、ページを更新したり、別のページに移動したりすると、フラッシュは表示されなくなる
変数flash
アクションで変数flash[:notice]に文字列を代入すると、flash[:notice]をビューで使うことができる。
変数flashは1度表示された後に自動で削除される
《posts_controller.rb》
def update
if @post.save
flash[:notice] = “更新に成功しました”
《layous/application.erb》
<% if flash[:notice] %>
<div class=”flash”>
<% flash[:notice] %>
</div>
<% end %>
- リスト
- リスト
新規投稿に失敗した時に、再び新規投稿ページを表示するようにする
エラーメッセージと直前の内容を表示する方法
《posts_controller.rb》
def create
@post = Post.new(content: params[:content])
render(“posts/new”) →newアクションを経由せずにposts/new.html.rbに直接表示する
《posts/new.html.rb》
<%= @post.errors.full_messages.each do |message| %> ←エラーメッセージの配列
<%= message %> →エラーメッセージを表示
<% end %>
<textarea><%= @post.content %></textarea> →直前の投稿内容を表示する
newアクションに@postを定義する
new.html.erbで変数@postを使用するようにしますが、newアクションではまだ変数@postが定義されていない
そのため、(localhost:3000/posts/newというURL)でアクセスしたときにエラーが出てしまう。
postにPost.newを代入しておけば、うまく動く
《posts_controller.rb》
def new
@post = Post.new
end
コメント