ド基礎だけど、RailsのActiveRelationにピンと来ていなかった頃に、わからなかった話。
先輩方がチャットでささっと説明しててなるほど!と思ったので残しておきます
User.where(id: 1) と User.find_by(id: 1)/User.find(1) の違い
どちらも、DBからデータを取ってきたい処理なのは確か。具体的にどう違うのか?
whereの方は、複数条件をつけて探すことができる、みたいなぼやっとした違いしか頭にうかばなかった。
whereを使う場合
where句を使うと、常にActiveRelationなので、遅延評価が行われる。
つまり、即座にSQL文が発行されて実行されるわけではない。
返される値のクラスは、ActiveRecord_Relation
になる。
[1] pry(main)> User.where(id: [1])
# => [#<User id: 1, email: "xxxxxx@sample.co.jp", created_at: "2017-03-30 01:56:31", updated_at: "2017-06-20 04:50:23"]
[7] pry(main)> User.where(id: 1).class
=> User::ActiveRecord_Relation
find_by もしくは、find を使う場合
即座にSQLを実行して、オブジェクトそのものを返す。
返される値のクラスは、ここではUser
になる。即座にSQLが実行されていることがわかる。
[1] pry(main)> User.find_by(id: 1)
# => [#<User id: 1, email: "xxxxxx@sample.co.jp", created_at: "2017-03-30 01:56:31", updated_at: "2017-06-20 04:50:23"]
[2] pry(main)> User.find(1)
# => [#<User id: 1, email: "xxxxxx@sample.co.jp", salt: nil, created_at: "2017-03-30 01:56:31", updated_at: "2017-06-20 04:50:23"]
[3] pry(main)> User.find_by(id: 1).class
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
=> User(id: integer, email: string, created_at: datetime, updated_at: datetime)
[3] pry(main)> User.find(1).class
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
=> User(id: integer, email: string, created_at: datetime, updated_at: datetime)
参考
この人の説明はわかりやすい。
https://stackoverflow.com/a/9574674