Ruby on RailsのCRUDを学ぶ。Select編。findメソッドとwhereメソッド
findメソッドとwhereメソッド
Railsでの、 selectは色々ありますが、大きく分けるとfindメソッドとwhereメソッドです。
ざっくり理解するのであれば、
一レコードを取得したい場合はfindメソッド
複数レコードを取得したいのであればwhereメソッド
という理解で問題ありません。
findメソッドとfind_byメソッド
find系のメソッドにはいくつか種類があるのですが、よく使うメソッドとしてfindメソッドとfind_byメソッドがあります。
findメソッドは引数にプライマリーキーの数字を渡すことでレコードを取得することができます。
Blog.find(1)
Blog Load (0.3ms) SELECT `blogs`.* FROM `blogs` WHERE `blogs`.`id` = 1 LIMIT 1
=> #<Blog id: 1, title: "奇数idの記事タイトル一括更新", content: "この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーで...", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:18:30">
railsのマイグレーションなどでテーブルを作成した場合は、デフォルトでidカラムが作成されるので検索したいレコードの値を渡して取得する形になります。
また、ここがfind_byメソッドとの違いですが検索する対象のレコードが見つからない場合はエラーとなります。
一方find_byメソッドは、カラム名を指定して検索を行うので、プライマリーキーでなくても検索を行うことができます。 (複数レコードがヒットした場合は最初にヒットしたレコードを返却します。)
Blog.find_by(category_id: 1)
=> #<Blog id: 1, title: "奇数idの記事タイトル一括更新", content: "この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーで...", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:18:30">
whereメソッド
複数レコードを取得したい場合は、whereメソッドを使用します。whereの引数には、様々な指定方法があり、もっともシンプルなのは、下記のようにカラムを指定して検索を行う形です。
log.where(category_id: 1)
Blog Load (0.3ms) SELECT `blogs`.* FROM `blogs` WHERE `blogs`.`category_id` = 1 LIMIT 11
=> #<ActiveRecord::Relation [#<Blog id: 1, title: "タイトル", content: "この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーで...", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:18:30">, #<Blog id: 2, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:01:05">, #<Blog id: 3, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:06:01">, #<Blog id: 4, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:01:05">, #<Blog id: 5, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:06:01">, #<Blog id: 6, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:01:05">, #<Blog id: 7, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:06:01">, #<Blog id: 8, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:01:05">, #<Blog id: 9, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:06:01">, #<Blog id: 10, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:01:05">, ...]>
配列を渡すと配列で指定した値を含むレコードを抽出してくれます。
Blog.where(id: [1, 2, 3])
Blog Load (0.3ms) SELECT `blogs`.* FROM `blogs` WHERE `blogs`.`id` IN (1, 2, 3) LIMIT 11
=> #<ActiveRecord::Relation [#<Blog id: 1, title: "タイトル", content: "この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーで...", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:18:30">, #<Blog id: 2, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:01:05">, #<Blog id: 3, title: "タイトル", content: "1万回のHello World", category_id: 1, created_at: "2018-07-13 12:30:55", updated_at: "2018-07-22 08:06:01">]>
複数のカラムを渡すとAND条件でレコードを抽出します。
Blog.where(id: [1, 2, 3], category_id: 1 )
ここまで見てきたwhere句の使い方だと不等号を使った比較ができないように見えますが、whereメソッドは文字列も渡すことができるので、不等号や曖昧検索などを使用したい場合はそちらを使います。
Blog.where('id < ?', 10 )
ハッシュので値を渡す形でも書くことができます。
Blog.where('id < :id', id: 10 )
まとめ
以下まとめになります。
- findメソッドは一レコード、whereは複数レコード
- findメソッドは、対象のレコードが見つからなかった場合に例外をかえす。
- whereメソッドの引数は多彩。文字列で渡す形とKeyと値のセットで渡す形を覚える
他テーブルとの結合やリレーションが絡んでくるとなかなか複雑になってくるので、まずはここの基本をしっかり抑えて頂ければと思います。