編集・削除ボタンの実装
課題の反省点
削除にdestroy!を使用していない。 コメントがついた投稿は削除させないといった制約がある時を除き、基本的にある投稿の削除が失敗することは考えられないので、失敗を想定していないなりの処理を記載する
→削除失敗が想定されない場合、destroy!と記載することで万が一に失敗した場合はシステムエラーとして処理を中断させ、おかしな挙動のまま機能を使わせない様にする。編集・削除ボタンの表示判定ロジックをboard.rb側に新たに作成していたが、user.rbに作った判定ロジックを汎用できるので無駄な記述となった。
コメントの編集・削除ボタン表示の際に用いた下記のロジックがそのまま使える。
user.rb
def own?(object) id == object.user_id end
新たに作ってしまった記述(要らない)
board.rb
def is_mine?(current_user) self.user == current_user end
掲示板自体の判定もuser.rbに記載したown?メソッドを用いて下記の様にビューで判定
<% if current_user.own?(board) %>
<%= render 'crud_menus', board: board if current_user.own?(board) %>
ルーティングの記載で何も考えずにonlyオプションにedit,update,destroyを追加していたが、CRUD機能全ての機能を使っているのだから、onlyオプションを消せば良いだけの話だった。無駄な記述に気づける様に注意する。
URLの直打ち対策にshowアクションまで含めていたため、他人の詳細画面に正規ルートでもアクセスできなくなっていた
実務における注意点
- 国際化対応は対応漏れが発生してしまうため、保留して後で行うことは基本的にない。その都度作ろう。
破壊的メソッドの使い分け
!
がある時とない時、処理が失敗した時の挙動に着目する。
例えばtitleとbodyが入力の必須項目だった場合、どちらかが空白のまま保存しようとするとバリデーションエラーが発生する。
挙動の違い
saveの場合
→falseを返す
save!の場合
→例外エラーを発生させる
- 処理が失敗する可能性が想定されており、失敗した場合に何かハンドリング(失敗した後の処理を指定)したい場合はsave
- 処理が必ず成功すると想定されており、万が一失敗した場合にその時点で処理を中断させたい場合はsave!と言う破壊的メソッドを使用する
ハンドリングとは
捕捉する、つかまえること。
※補うではない
エラーに気づく
対処する
の内エラーに気づくこと、エラーを拾うことをエラーハンドリングという。人により、エラーに気付き対処するまでをエラーハンドリングと言うことがあるため、文脈で判断する。
確認ダイアログ
送信、削除などした時に画面上部に現れる「削除して良いですか?」のような確認表示のこと。
data
属性を使用する。
(ちなみに自分はdataを頻繁にdateと書き間違えるので注意)
<%= link_to 'リンク', ○○_path, data: { confirm: '確認ダイアログメッセージ' } %>
- data属性とは、HTML5より使用されたカスタムデータ属性と呼ばれるもの。
- data-confirm属性の場合は、値として設定された文言を確認ダイアログの中で表示させるという役割が決められている
- 複雑なJSなどの定義を行わなくても、簡単に表示させることができる
- ダイアログの見た目を変更したい場合は、
Data-Confirm Model
などを用いる
URL直打ちの対処
判定ロジックにて、current_userの投稿にのみ編集・削除ボタンを表示させたところでURLのID部分を変更してアクセスしてしまえば、簡単に他人の投稿を編集・削除できてしまう。
@post = Post.find(params[:id]) @post.destroy!
上記の様に書いてしまうとURLの直打ちで削除ができてしまうため、下記の様に記述することでcurrent_userの投稿の中からある投稿を取得する様に書き換える。
@post = current_user.posts.find(params[:id])
※ postとuserが紐づいていること、sorceryを使ってログイン機能を実装している前提でcurrent_user使用