我有一个简单的模型“用户”,有很多字段。在Controller的show
操作中,我想限制从数据库中获取的字段数(构建投影)。所以,而不是
SELECT "users".* FROM "users" ...
我想发出
SELECT id, first_name, last_name, email FROM "users" ...
我认为,我已经完成了这项工作,但效果不佳:Rails发出两个数据库查询。
为此,我在模型中定义了scope
:
class User < ActiveRecord::Base
...
scope :brief, -> (id) { select('id, first_name, last_name, email').where('id == ?', id) }
end
Controller的show
操作定义为此
def show
if derived_version >= 2
@user = User.brief(params[:id])
else
@user = User.find(params[:id])
end
end
(使用版本蛋糕进行版本控制)
在版本2中,范围用于构建投影。版本1只包含关系中的所有列。
这是有效的,除了Rails在使用范围时发出两个数据库查询,其中FIRST是奇数:
Started GET "/api/users/2?api_version=2" for 127.0.0.1 at 2013-06-15 19:49:11 +0200
Processing by Api::UsersController#show as JSON
Parameters: {"api_version"=>"2", "id"=>"2"}
User Load (0.1ms) SELECT id, first_name, last_name, email FROM "users" WHERE (id == '2') ORDER BY "users"."id" ASC LIMIT 1
User Load (0.3ms) SELECT id, first_name, last_name, email FROM "users" WHERE (id == '2')
Rendered api/users/show.v2.json.rabl (89.0ms)
Completed 200 OK in 99ms (Views: 92.5ms | ActiveRecord: 1.0ms)
当我在这种情况下切换到版本1时
@user = User.find(params[:id])
将被执行,日志就像我期望的那样:
Started GET "/api/users/2?api_version=1" for 127.0.0.1 at 2013-06-15 20:03:56 +0200
Processing by Api::UsersController#show as JSON
Parameters: {"api_version"=>"1", "id"=>"2"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", "2"]]
Rendered api/users/show.v1.json.rabl (1.1ms)
Completed 200 OK in 6ms (Views: 4.5ms | ActiveRecord: 0.3ms)
我尝试过多种变体,例如将select()。where()直接放入控制器的show
动作中,但结果总是相同的:当使用select()时,OR在哪里()或select()。where()Rails生成两个查询。
所以,在我提出最后一个问题之前,我需要补充一点,我不是Rails专家。
我是否认为Rails实际上执行了这两个数据库查询?
发出两个查询是否有任何好的/令人信服的理由?