見出し画像

完全理解!Rails findについて

findメソッドをなんとなく使ってる。
findメソッドの使い方がわからない。

そんな方へ向けて書きました!

今回は、Ruby on Rails(以下Rails)のfindメソッドについて、Rails初心者でもわかるように、具体的なソースコードを用いながら解説してみました。

私自身Railsを使って仕事を始めた際、findメソッドについて理解できるようになるまでかなり苦労しました。公式ドキュメントを見ても書いてあることが難しく、理解できなかったことを今でも覚えてます・・・。今回は、findメソッドについてなるべく難しい用語を使わず、最低限必要な用語だけを用いて解説するよう試みました。
私と同じような苦労をしていらっしゃる方でも、本記事を読み終える頃には、Rails findメソッドについて完璧に理解できている状態になれます!

findメソッドについて

まずは、findに関する簡単なご説明です。

findは、データベースからデータを取得する際に使用するメソッドです。つまり、データベースに保存したデータの中から自分が欲しいデータを取得する際に用いるメソッドになります。

findメソッドの使い方

まず文法についてですが、下記のような記述の仕方をします。

class名.find(主キーの値)

書き方についてはルールなので覚えてしまいましょう。当然ですが、上記の書き方では動きません。大事な部分は、class名主キーの値 です。1つずつ見ていきましょう。

class名について
この class名 の部分に関しては、自分が取得したいレコードが保存されているテーブルのモデルのclass名を指定します。
たとえば、users テーブルからレコードを取得したい場合は、

User.find(主キーの値)

となります。なぜなら、usersテーブルに対応するモデルは User モデルであり、そのモデルのclass名は User だからです。これはルールなので覚えてしまいましょう。

主キーの値について
次に、主キーの値についてです。主キーというと難しく感じる方も多いかと思いますが、これは最低限覚えておかないといけないことなので、この機会に覚えてしまいましょう。
主キーとは、

データベースのデータ(行、レコード)を一意に識別するための項目

です。主キー目的レコードを一意に識別することなので、重複することがありません。Railsでは多くの場合、idが主キーとなります。

画像1

主キーの値とは、つまり、テーブルのidカラムの値を指定するということです。

たとえば、idが1のレコードを取得したい場合は、

User.find(1)

となります。

ここまでの内容で覚えておくことまとめ

findメソッドとは?
→ データベースからデータを取得する際に使用するメソッド
使い方は?
Class名.find(id)
主キーってなに?
→ データベースのデータ(行、レコード)を一意に識別するための項目

Railsでプログラミングをする時には、findメソッドを必ずと言っていいほど使用します。使い方を忘れてしまった時は、ぜひ本記事を読みなおしてRails findメソッドを思い出してください。

ここまではfindメソッドの基礎的な解説でした。
Railsエンジニアとしてのキャリアを考えられている方は、上記の基礎的な解説にとどまらず、さらに理解を深める必要があります。

ここからは、

rails console(省略系は rails c)を使用しながらfindメソッドについて見ていきたいと思います。

rails c

まず、findメソッドを実行してみます。すると下記のような処理が実行されます。

irb(main):001:0> User.find(1)
  (1.0ms)  SELECT sqlite_version(*)
 User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "test1", created_at: "2021-04-03 13:52:14.218816000 +0000", updated_at: "2021-04-03 13:52:14.218816000 +0000">

データベースからレコードを取得するメソッドを実行すると必ずSQL文が発行されます。

ここで大事なのは下記の流れを理解することです。

find → SQLを発行 → 発行されたSQLをデータベースが実行 → 値を取得

つまり、findメソッドが実際にやっていることは、

SQLを発行する

ということです。その発行されたSQLをデータベースが実行することで、取得したいデータが取得できるようになります。
では、発行されたSQLを見ていきます。

SELECT "users".* 
FROM "users" 
WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]

FROMで指定するものは、取得したいレコードが保存されているテーブルです。
SELECTでは、対象となるテーブルのどのカラムを取得するかを指定する命令です。*(アスタリスク)を指定すると、対象のテーブルの全てのカラムという意味になります。今回は、

"users".* 

となっているので、"users"(テーブルの).*(全てのカラム)という意味になります。
そして、WHEREで取得したいレコードの絞り込みを行います。
今回は、find(1) と指定していることから、id=1のレコードを絞り込みたいので、WEHRE句に "user"."id" = 1 とすることでid=1のレコードに絞り込むことができます。

WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]

ちなみに、上記のクエリで LIMIT がついている理由はRailsの内部で limit(1) を実行しているからです。興味がある方はRails内部のコードを覗いて見ると良いと思います。

複数のデータを取得したい場合

仮に複数のデータを取得したい場合、引数に取得したいデータのidを複数与えてあげればデータを取得することができます。

User.find(1,2)
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (?, ?)  [[nil, 1], [nil, 2]]
=> [#<User id: 1, name: "test1", created_at: "2021-04-03 13:52:14.218816000 +0000", updated_at: "2021-04-03 13:52:14.218816000 +0000">, #<User id: 2, name: "test2", created_at: "2021-04-03 13:52:14.879338000 +0000", updated_at: "2021-04-03 13:52:14.879338000 +0000">]

ただし、注意したい点として、findメソッドを使用して複数のデータを取得した場合、そのデータのクラスが配列になってしまいます。

irb(main):003:0> User.find(1,2).class
 User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN (?, ?)  [[nil, 1], [nil, 2]]
=> Array

一方で、whereを使用すればデータのクラスがActiveRecordになるので、実装しやすくなります。

irb(main):004:0> User.where(id: [1,2]).class
=> User::ActiveRecord_Relation

存在しないidを指定するとどうなるか?

存在しないidを指定した場合、findメソッドの場合はエラーが起きます。

irb(main):005:0> User.find(0)
 User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 0], ["LIMIT", 1]]
Traceback (most recent call last):
       1: from (irb):5
ActiveRecord::RecordNotFound (Couldn't find User with 'id'=0)

プログラムを始めたばかりの方はエラーになると聞いて「嫌だな」と思われるかもしれませんが、エラーが起きるのは正しい動作なのであまり気にする必要はありません。エラーはプログラムが開発者に解決のヒントを与えてくれているのです。

ActiveRecord::RecordNotFound (Couldn't find User with 'id'=0)

このエラーの意味ですが、ActiveRecord::RecordNotFound という種類のエラーが起きたという意味になります(正確に記述すると、ActiveRecord::RecordNotFoundという例外クラスがraiseされたということになります)。そして、詳細な理由は右カッコ内に記述されています。

Couldn't find User with 'id'=0

英語で記述されている通り、id=0 というレコードを探したけど、そんなidを持つUserは見つからなかったよ と言ってくれています。
先ほど、エラーはヒントと書きましたが、このエラー文からRailsが下記のヒントを与えてくれていると解釈できます。

id=0 っていうレコードがない = idは間違っていないか確認してね!

そして、このヒントが得られたら次にするべきは指定したidを持つレコードが存在するか確認することです。確認する方法はいくつかありますが、rails cで対象のデータを全て取得してみるのも良いでしょう。

User.all

例えば、全てのレコードを取得してみて、その中にfindの引数で指定したidを持つレコードが存在するか確認することもできます。

ここまで書いてきたように、findというメソッドがどのような場合に、どのような処理を行うのかということを理解することで、何かプログラムを書くときにfindメソッドを使うことができるようになると思います。

今回は以上となります。

読んでいただき、ありがとうございました!

ぜひ、ツイッターなどで、感想などをツイートしていただけると幸いです!




この記事が気に入ったらサポートをしてみませんか?