在 Rails 5.1 之後,使用 pluck 不保證會 DB query
- Backend
- 01 May, 2020
在 Rails 5.1 之後,因為這個 commit,為 pluck 的行為帶來的一點變動。
因為習慣在 Rails 4.2 開發,養成了一個直覺是使用 pluck 就是會 DB query。但是就在換到 Rails 5.2 之後遇到這個改變了。
以下是在兩種環境用 Rails console 實驗的結果:
Rails 4.2.11.1 & Ruby 2.5.7 & MySQL 5.6
> users = User.where(id: 1); nil
> users.load; nil
# User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
> users.pluck(:name)
# (0.2ms) SELECT `users`.`name` FROM `users` WHERE `users`.`id` = 1
# => ["Allen"]
Rails 5.2.4.2 & Ruby 2.5.7 & MySQL 5.6
> users = User.where(id: 1); nil
> users.load; nil
# User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
> users.pluck(:name)
# => ["Allen"]
可以發現在 Rails 5.2 的實驗,users 在 load 之後,就不會去 DB query 了。
上面的例子看起來沒有什麼問題,但如果你很習慣用 association 去組 query,下面的例子可能就需要注意:
> Post.where(user_id: 1).update_all(content: 'old')
> user = User.find(1); nil
> user.posts.load; nil
> user.posts.pluck(:content)
# => ["old"]
> Post.where(user_id: 1).update_all(content: 'new')
> user.posts.pluck(:content)
# => ["old"]
> user.reload.posts.pluck(:content)
# => ["new"]