This is Rails 4.0.0.rc2, creating a versioned API.
I've a simple model "User" with a number of fields. In the Controller's show
action I would like to restrict the number of fields fetched from the database (building a projection). So, instead of
SELECT "users".* FROM "users" ...
I would like to issue
SELECT id, first_name, last_name, email FROM "users" ...
I think, I have accomplished this, but with an undesired effect: Rails issues two database queries.
The Details
For that purpose I've defined a scope
in the Model:
class User < ActiveRecord::Base
...
scope :brief, -> (id) { select('id, first_name, last_name, email').where('id == ?', id) }
end
The Controller's show
action is defined as this
def show
if derived_version >= 2
@user = User.brief(params[:id])
else
@user = User.find(params[:id])
end
end
(using versioncake for versioning)
In versions 2 the scope is used building the projection. Version 1 simply includes all columns in the relation.
This works, except that Rails issues TWO database queries when the scope is used, with the FIRST being odd:
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)
When I switch to version 1 in which case
@user = User.find(params[:id])
will be executed, the log is as I would expect it:
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)
I've tried a number of variations, for example putting the select().where() directly into the controller's show
action, but the result is always the same: when using select(), OR where() OR select().where() Rails generates two queries.
So, before I ask the final question, I need to add, that I'm in no way a Rails expert.
The Questions
Am I right in the assumption that Rails actually performs these two database queries?
Is there any good/compelling reason for issuing two queries?