【Rails】find・find_by・whereについてまとめてみた

#はじめに
今回はfind・find_by・whereについて紐解いていきます。

#バージョン
rails:**5.1.6**

#find
主キーに対応するレコードを取り出すことができる。


```ruby
#主キー(id)が1のbookを検索
> Book.find(1)

=> #<Book:0x007fb51c8131b0
 id: 1,
 title: "hoge",
 price: 1250,
 publish: "fuga",
 created_at: Sat, 05 May 2018 05:42:47 UTC +00:00,
 updated_at: Sat, 05 May 2018 05:42:47 UTC +00:00>
```
###主キーを複数指定することも可能

```ruby
> Book.find(1,2)  #Book.find([1,2])でも可
=> [#<Book:0x007fb51b0636f0
  id: 1,
  title: "hoge",
  price: 1250,
  publish: "fuga",
  created_at: Sat, 05 May 2018 05:42:47 UTC +00:00,
  updated_at: Sat, 05 May 2018 05:42:47 UTC +00:00>
 #<Book:0x007fb51b062778
  id: 2,
  title: "test",
  price: 960,
  publish: "test",
  created_at: Sat, 05 May 2018 05:58:20 UTC +00:00,
  updated_at: Sat, 05 May 2018 05:58:20 UTC +00:00>]
```

###主キーが見つからない場合

```ruby
Book.find(100)
=> ActiveRecord::RecordNotFound: Couldn't find Book with 'id'=100
```

ActiveRecord::RecordNotFound例外が発生する。

###複数主キーを指定し、一方が見つからなかった場合
```ruby
Book.find(1,100)

=>ActiveRecord::RecordNotFound: Couldn't find all Books with 'id': (1, 100) (found 1 results, but was looking for 2)
```

こちらもActiveRecord::RecordNotFound例外が発生する。

###findで取得したオブジェクトのクラス
```ruby
Book.find(1).class
=> Book(id: integer, title: string, price: integer, publish: string, created_at: datetime, updated_at: datetime)
```
findで取得したオブジェクトのクラスはBook　

###複数取得した場合のクラス

```ruby
Book.find(1,2).class
=>Array
```

二つ取得した際にはActiveRecord_Relationではなく、Arrayクラスになるので注意！


###findのまとめ
・主キーに対応するレコードを取り出す
・主キーを複数指定することも可能
・主キーが１つでも見つからない場合ActiveRecord::RecordNotFound例外が発生する
・findで取得したオブジェクトのクラスはBook　


#find_by
与えられた条件にマッチするレコードのうち最初のレコードだけを返す。

```ruby
Book.find_by(id: 2)
=>#<Book:0x007fb51b758168
 id: 2,
 title: "test",
 price: 960,
 publish: "test",
 created_at: Sat, 05 May 2018 05:58:20 UTC +00:00,
 updated_at: Sat, 05 May 2018 05:58:20 UTC +00:00>
```

###主キー以外も検索条件にできる
```ruby
#titleが「test」である最初のレコードを取得
Book.find_by(title: "test")
=> #<Book:0x007fb51b0ba748
 id: 2,
 title: "test",
 price: 960,
 publish: "test",
 created_at: Sat, 05 May 2018 05:58:20 UTC +00:00,
 updated_at: Sat, 05 May 2018 05:58:20 UTC +00:00>
```



###条件を複数指定できる
```ruby
#titleが「test」でなおかつ,priceが「960」の最初のレコードを取得
> Book.find_by(title: "test", price: 960)
=>#<Book:0x007fb51b6c9058
 id: 2,
 title: "test",
 price: 960,
 publish: "test",
 created_at: Sat, 05 May 2018 05:58:20 UTC +00:00,
 updated_at: Sat, 05 May 2018 05:58:20 UTC +00:00>
```

###条件に一致するものがない場合
```ruby
Book.find_by(title: "rails")
=> nil
```

nilを返す。

###条件を複数指定し、１つ以上の条件が満たされなかった場合
```ruby
Book.find_by(title: "test", price: 960, publish: "fuga")
=> nil
```

こちらも先ほど同様nilを返す。

###find_byで取得したオブジェクトのクラス
```ruby
Book.find_by(title: "test" ).class
Book(id: integer, title: string, price: integer, publish: string, created_at: datetime, updated_at: datetime)
```

find_byで取得したオブジェクトのクラスはBook

###find_byのまとめ
・与えられた条件にマッチするレコードのうち最初のレコードだけを返す
・条件を複数指定することができる
・与えられた条件がない場合nilを返す
・find_byで取得したオブジェクトのクラスはBook

#where
与えられた条件にマッチするレコードをすべて返す。

```ruby
#titleが「test」にマッチするレコードを全て取得
Book.where(title: "test")
=> [#<Book:0x007f978ebe0960
  id: 2,
  title: "test",
  price: 960,
  publish: "test",
  created_at: Sat, 05 May 2018 05:58:20 UTC +00:00,
  updated_at: Sat, 05 May 2018 05:58:20 UTC +00:00>,
 #<Book:0x007f978ebe0780
  id: 10,
  title: "test",
  price: 800,
  publish: "fuga",
  created_at: Mon, 17 Sep 2018 15:30:55 UTC +00:00,
  updated_at: Mon, 17 Sep 2018 15:30:55 UTC +00:00>]
```

###NOT条件
```ruby
#titleが「test」以外のレコードを全て取得
Book.where.not(title: "test")
=> [#<Book:0x007fa69edaefc0
  id: 1,
  title: "hoge",
  price: 1250,
  publish: "fuga",
  created_at: Sat, 05 May 2018 05:42:47 UTC +00:00,
  updated_at: Mon, 17 Sep 2018 16:34:17 UTC +00:00>,
 #<Book:0x007fa69edaed90
  id: 3,
  title: "ruby",
  price: 1200,
  publish: "ruby",
  created_at: Sat, 25 Aug 2018 04:26:19 UTC +00:00,
  updated_at: Sat, 25 Aug 2018 04:26:19 UTC +00:00>]
```


###AND条件
```ruby
#titleが「test」で、なおかつpriceが「960」のレコードを全て取得
#Book.where(title: "test", price: 960)でも可
Book.where(title: "test").where(price: 960)
=>  [#<Book:0x007fa69c31c910
  id: 2,
  title: "test",
  price: 960,
  publish: "test",
  created_at: Sat, 05 May 2018 05:58:20 UTC +00:00,
  updated_at: Sat, 05 May 2018 05:58:20 UTC +00:00>]
#<Book:0x007fa6a0867358
  id: 11,
  title: "test",
  price: 960,
  publish: "fuga",
  created_at: Mon, 17 Sep 2018 17:07:26 UTC +00:00,
  updated_at: Mon, 17 Sep 2018 17:07:26 UTC +00:00>]
```

###OR条件(Rails5から)
```ruby
#titleが「hoge」かpriceが「800」のレコードを全て取得
Book.where(title: "hoge").or(Book.where(price: 800))
=>[#<Book:0x007fa6a08c4c10
  id: 1,
  title: "hoge",
  price: 1250,
  publish: "fuga",
  created_at: Sat, 05 May 2018 05:42:47 UTC +00:00,
  updated_at: Mon, 17 Sep 2018 16:34:17 UTC +00:00>,
 #<Book:0x007fa69ea73798
  id: 10,
  title: "test",
  price: 800,
  publish: "fuga",
  created_at: Mon, 17 Sep 2018 15:30:55 UTC +00:00,
  updated_at: Mon, 17 Sep 2018 15:30:55 UTC +00:00>]
```

###A and B or C
```ruby
#titleが「hoge」かつpublishが「fuga」のレコードまたは、priceが960のレコードを取得
Book.where(title: "hoge").where(publish: "fuga").or(Book.where(price: 960))
[#<Book:0x007fa6a08d56c8
  id: 1,
  title: "hoge",
  price: 1250,
  publish: "fuga",
  created_at: Sat, 05 May 2018 05:42:47 UTC +00:00,
  updated_at: Mon, 17 Sep 2018 16:34:17 UTC +00:00>,
 #<Book:0x007fa6a08d5588
  id: 2,
  title: "test",
  price: 960,
  publish: "test",
  created_at: Sat, 05 May 2018 05:58:20 UTC +00:00,
  updated_at: Sat, 05 May 2018 05:58:20 UTC +00:00>,
 #<Book:0x007fa6a08d5448
  id: 11,
  title: "test",
  price: 960,
  publish: "fuga",
  created_at: Mon, 17 Sep 2018 17:07:26 UTC +00:00,
  updated_at: Mon, 17 Sep 2018 17:07:26 UTC +00:00>]
```

###条件にマッチしなかった場合
```ruby
Book.where(title: "fuga")
=> []
```
ActiveRecord_Relationクラスを返す。空の配列ではないので注意。

###whereで取得したオブジェクトのクラス
```ruby
Book.where(title: "hoge").class
=> Book::ActiveRecord_Relation
```

whereで取得したオブジェクトのクラスはBook::ActiveRecord_Relation

###whereのまとめ
・与えられた条件にマッチするレコードをすべて返す。
・NOT条件
・AND条件
・OR条件
・条件にマッチしない場合は空の配列を返す
・取得したオブジェクトのクラスはBook::ActiveRecord_Relation


#終わりに
お疲れ様でした(^_^)
もっと詳しく知りたい方は[こちら](https://railsguides.jp/active_record_querying.html)に記載されております。
ご意見やご質問等ございましたらコメントいただけると幸いです。

#参考
[RAILS GUIDES](https://railsguides.jp/active_record_querying.html)