findとfind_byについて(セキュリティ面)
findを主に使用していましたが、find_byというものを知り、役割の区別がつきにくかったので、
理解のために残します。
find メソッド
IDに基づいてレコードを検索する。
見つからない場合、ActiveRecord::RecordNotFound を発生させます。
このメソッドは、主にIDを使ってデータベースからレコードを検索する際に使用されます。
例えば User.find(3) というコードは、IDが3のUserを検索し、
存在しない場合は ActiveRecord::RecordNotFound というエラーを発生させます。
このエラーは、レコードが見つからない場合に表示されます。
find_by メソッド
指定された条件にマッチする最初のレコードを返します.
見つからない場合は nil を返します。
この違いは、エラーハンドリングの戦略を決定する際に重要です。
例えば User.find_by(name: 'Kaushik') というコードは、nameが 'Kaushik' のUserを検索し、存在しない場合は nil を返します。
これにより、エラーを発生させずに、レコードが存在しない場合の条件分岐を簡単に記述できます。
エラーページを表示したい場合は find を使用します。これにより、IDに基づいてレコードが確実に存在することを保証し、存在しない場合はエラーを吐いてくれます。
エラーを回避したい場合は find_by を使用します。
これにより、例外ハンドリングを行わずに、nil チェックをすることで処理を分岐できます。
find_byを使用するのは、showとかに使用します。
この例では、
def show
@user = User.find_by(id: params[:id])
unless @user
redirect_to root_path, alert: "指定されたユーザーは存在しません。"
end
end
を使用してユーザーを検索し、ユーザーが見つからない場合にはルートパスにリダイレクトしてアラートを表示します。
セキュリティ観点からの選択
find`メソッド: IDに基づいてデータベースから直接レコードを取得しようとします。レコードが見つからない場合はエラーがでます(URLに直接番号を変更させるなどしてURLを変更した場合)
find_by`メソッド: より柔軟に条件を指定でき、レコードが見つからない場合には nil を返すため、例外ハンドリングの必要がありません。これは、ユーザーが存在しない可能性がある場合や、エラーを起こさず指示したルートに戻ります。
(URLに直接番号を変更した場合、指定したページに戻る)
補足
結論、どっちが良い?となれば、僕はfindで使用しています。理由はその次の記事に載せます。
不慣れでかなり文字が増えたので、よりもっと簡単に。という方は下の記事を参考にしてください。
Discussion