1

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?

4

0 回答 0