らんぼーのエンジニア日記

不定期にサクッと更新していきます

ActiveRecord frist,take,limitの違い

今回はfirst,take,limitの挙動の違いに躓きましたのでまとめました。

間違いなどありましたら、ご教示頂けますと幸いです。

first

前提としてUserクラスが存在するとします。

クエリを見てみると・・・

pry(main)> user = User.first
  User Load (0.7ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]

orderされています!!!

pry(main)> User.pluck(:id,:name)
=> [[2, "田中"], [1, "佐藤"]]
pry(main)> user.first.id
=> 1
pry(main)> user.first.name
=> '佐藤'

ですので、レコードのIDが昇順になっていなくてもorderしてくれるので最もidが若いものを取得できています。

take

pry(main)> user = User.take 
 User Load (0.7ms)  SELECT  "users".* FROM "users" LIMIT $1  [["LIMIT", 1]]

firstのようにorderはされていません。

pry(main)> User.pluck(:id,:name)
=> [[2, "田中"], [1, "佐藤"]]
pry(main)> user.first.id
=> 2
pry(main)> user.first.name
=> '田中'

ですので、DBの先頭に保存されているレコードがそのまま取得されてしまいます。

limit

pry(main)> user = User.limit(1)
=>  User Load (0.4ms)  SELECT  "users".* FROM "users" LIMIT $1  [["LIMIT", 1]]

limitは引数を指定しないと使えません。

pry(main)> User.pluck(:id,:name)
=> [[2, "田中"], [1, "佐藤"]]
pry(main)> user.first.id
=> 2
pry(main)> user.first.name
=> '田中'

また、limittakeと同じようにorderはしてくれません

pry(main)> User.limit(1).class
=> User::ActiveRecord_Relation

ただfirsttakeと異なるのがlimitは、返り値がActiveRecord_Relationになります。

scopeなどでメソッドチェーンをしたいときは、limitの方がいいかもしれません。

参考資料

http://at284km.hatenablog.com/entry/2016/06/22/025824