しっかり使い分け!Railsでのfind, find_byの違い、使い方

こんにちは! フリーエンジニアの長瀬です。

Railsでは、ActiveRecordによってデータベース内のデータを検索することができます。

ただ、似たようなメソッドが多いため、どう違うのか、どう使い分けたらいいのかって分かりづらいですよね。

そこで、この記事では、Raildのfind/find_byメソッドについて

・ Railsのfindについて
・ Railsのfind_byについて
・ 検索条件の違い
・ 取得データ数の違い
・ 検索結果がない場合の挙動

を学習した後

・ Rubyのfindについて
・ Rubyのfind_allについて
・ Rubyのselectについて
・ Rubyのselect!について
・ Rubyのrejectについて
・ Rubyのanyについて
・ Rubyのallについて

といったRubyのメソッドについても解説していきます。

Rubyにもfindメソッドがあるので、Railsのfindメソッドと混同しないように後半で紹介します。

目次

Railsのfindについて

findは「id」によってデータを取得します。

Railsでは、デフォルトで「id」カラムがプライマリキーとしてデータベースに追加されるため、特に何も設定することなくfindメソッドを使うことができます。

基本形

基本形は、モデル名にfindをつなげて引数を指定します。

それによって、該当するモデルのテーブルからデータを検索できます。

モデル名.find(*args)

指定できる引数は

  • 数値型
  • 文字列の数字
  • 数字のリスト
  • 数字の配列

の4つです。

なお、該当するidのデータが見つからない場合は例外(RecordNotFound)が発生します。

使い方

Userテーブルの中からidが1のデータを返す

User.find(1)

文字列の数字でも数値型に変換してくれるので、検索可能。

User.find("1")

余計な文字列が入っていても、一番最初にマッチした文字数字をidとして検索してくれる。

User.find("3-samurai") # Userテーブルの中からidが3のデータを返す

リストでidを指定した場合はデータを複数検索して、配列で返す。

User.find(1, 2, 6) # idが1,2,6のデータをそれぞれ検索して配列で返す

配列でも指定可能。

User.find([7, 17, 20]) # idが7,17,20のデータをそれぞれ検索して配列で返す

Railsのfind_byについて

特定の条件にマッチした最初のレコードを検索します。

取得できるデータは1件のみです。

複数のデータを特定の条件で取得したい場合は、whereメソッドを使いましょう。

特定の条件で検索を行いますが、同じデータが複数あるときに、順序が重要になる場合があります。

その場合は、orderメソッドを使うなどして自身でデータの順序を指定する必要があるので注意しましょう。

基本形

モデル名にfind_byメソッドをつなげて引数を1つ以上指定します。

モデル名.find_by(特定の条件)

指定できる引数には

  • カラム名
  • 検索条件

などが使えます。

なお、データが見つからなかった場合はnilを返します。

使い方

Userテーブルからnameカラムが「侍」とマッチした最初のデータを取得する。

User.find_by(name: '侍')

Userテーブルからnameカラムが侍で、かつ管理者(adminカラムがtrue)である最初のデータを取得する。

User.find_by(name: '侍', admin: true)

Userテーブルから作成日が1週間以内のデータを1件取得する。

User.find_by("created_at > ?", 1.weeks.ago)

両者の違いについて

検索条件の違い

findは検索条件として指定できるものは「idのみ」です。

find_byは、複数の条件を指定したりid以外のカラムでも検索できます。

取得データ数の違い

findはデータを複数取得できます。

find_byは最初にマッチした1件のみ取得できます。

検索結果がない場合の挙動


・findは例外を発生させて処理を中断します。

・find_byはnilを返すため処理は中断されません。
s
findでは検索した結果、データの有無をチェックする必要がありません。

そのため、例外処理を使い検索結果が0件の場合に処理をまとめて書くことが可能です。

findを使う場合は、データを削除した後にリクエストがあった場合にエラーページを表示する、rootにリダイレクトさせるなどが考えられます。(例:ユーザーがサービスを退会してデータを削除されたあとに、自分のプロフィールページにアクセスしてきた場合)

id以外の検索条件で1件のデータを取得したい場合、または検索データの有無によって特別な処理をしたい場合はfind_byを使うようにするといいでしょう。

なお、whereは複数のデータを検索した場合、より複雑な検索条件を指定する場合に使われることが多いです。

whereの使い方はこちらで解説してあるので、whereについて不安がある人は一読することをおすすめします。

Rubyのメソッド

ここからはRailsではなくて、Rubyのメソッドを紹介します。

Railsのfind、find_byメソッドとは似て非なるものなので、混同しないように注意しましょう。

Rubyのfindについて

Railsのfindメソッドはテーブルから特定のidを指定して、データを取得するものでしたが、Rubyでのfindメソッドは条件によって配列にフィルターをかけるメソッドです。

特にRubyのfindメソッドは条件に一致した始めの要素を1つだけを返します。

サンプルコードで確認してみましょう。

array = [1,2,3,4,5]
p array.find{|num| num > 2}

[実行結果]

3 

このように、条件に従って、findは先頭の要素だけを返します。

この場合は1〜5の数字の中から、2より大きかった1番始めの数字3を返しています。

Rubyのfind_allについて

Rubyにはfindメソッドの他にfind_allメソッドもあります。

こちらは、実は後述するselectメソッドと全く同じメソッドです。

さきほどのfindメソッドが条件を満たした1番始めの要素を返したのに対して、find_allメソッドはallの名前の通り、条件を満たすすべての要素を返します。

サンプルコードで確認してみましょう。

array = [1,2,3,4,5]
p array.find_all{|num | num > 2}

[実行結果]

[3,4,5]

このように、このサンプルコードでは2以上である配列の要素すべて返しています。

Rubyのselectについて

Rubyのselectメソッドは先ほど紹介したfind_allメソッドとまったく同じメソッドです。

なので、条件を満たしている配列の要素をすべて返します。

サンプルコードで確認してみましょう。

array = [1,2,3,4,5]
p array.select { |num| num > 3 }
p array.select { |num| num == 3 }
p array.select { |num| num <= 3 }

[実行結果]

[4, 5]
[3]
[1, 2, 3]

このように

・1番目では3以上
・2番目は3と完全に一致したもの
・3番目は3以下という条件を満たしたもの

を返しています。

Rubyのselect!について

select!メソッドは、selectメソッドを破壊的メソッドにしたものです。

先ほどのselectメソッドではレシーバー(元の配列)は変更されませんでしたが、select!メソッドは元の配列に変更を加えます。

サンプルコードで確認してみましょう。

array = [1,2,3,4,5]
array.select! {|num| num > 3} 
p array 

[実行結果]

[4,5]

このように、元の配列は[1,2,3,4,5]でしたが、select!メソッドで返った結果に変更されています。

Rubyのrejectについて

find_all/selectの条件を反転させたrejectというメソッドも使用可能です。

少しややこしい表現になりますが、指定した条件以外のもので配列を作成します。

サンプルコードで確認してみましょう。

array = [1,2,3,4,5]
p array.reject{|num| num > 3}

[実行結果]

[1, 2, 3]

このように、3よりも大きな数字という条件に一致しないものが出力されます。

つまり、3よりも大きくない数字です。

Rubyのanyについて

Rubyのanyメソッドは、配列の中に条件に一致しているものが1つでもあれば、trueを返し1つも含まれていない場合はfalseを返します。

サンプルコードで確認してみましょう。

array = [1,2,3]
array.any?{|a| a > 2}

[実行結果]

true

この場合2以上の数値である3が配列arrayに含まれているので、trueが返っています。

Rubyのallについて

Rubyのallメソッドはanyメソッドとは対照的に、配列のすべての要素が条件を満たす時にtrueを返し、それ以外のときはfalseを返します。

サンプルコードで確認してみましょう。

array = [1,2,3]
array.all?{|a| a > 2}

[実行結果]

false

anyの場合と同じ条件式ですが、見ての通り2以上のものはすべてではないので、falseが返っています。

まとめ

いかがでしたでしょうか?

この記事では、Railsのfind/find_byメソッドを主に解説しました。

Railsのfindメソッドは、idを指定してモデルからデータを取得し、find_byメソッドは任意の条件によって最初にマッチした1件を取得できるのでしたね。

findメソッドは例外を発生させて、find_byメソッドはnilを返すということも重要な違いなのでしっかりと覚えておきましょう。

また、findメソッドにちなんで、Rubyのfindメソッドやその他の関連性のあるメソッドを紹介しました。

Railsはいうまでもなく、「Ruby」で作られているので、Rubyの基礎も意欲的に学んでいきましょう。

この記事を書いた人

Unityを使ったiOSアプリのリリース、フリマサイト運営の経験があります。

経験した言語はC、C#、Javascript、R、Python、Ruby、PHPなど

言語が好きで、英語や中国、ドイツ語を勉強しました。
将来的には海外で生活したいです。

現在はRuby on Rails5やCocos2dxの勉強を主にしています。

ライターとしては
できるだけ初心者にわかりやすい文章になるように心がけています。

趣味は語学、読書です。

目次