LogoDTreeLabs

Rails 6 adds reselect on ActiveRecord Relation

Akshay MohiteBy Akshay Mohite in Ruby on RailsActiveRecordRuby on December 4, 2019

Sometimes, we need to remove selected columns and select new columns for the query being done. Rails 6 introduces reselect on ActiveRecord#Relation on query methods. This lets us easily select new columns.

Consider, Post schema as given below.

class Post < ApplicationRecord {
  :id          => :integer,
  :user_id     => :integer,
  :title       => :string,
  :description => :text,
  :status      => :string,
  :created_at  => :datetime,
  :updated_at  => :datetime
}

Now let’s say, we need to show post ID, title and description for all the posts on UI of user with ID = 5. In order to get these attributes, we will query as given below with ActiveRecord.

posts = Post.where(user_id: 5).select(:id, :user_id, :title, :description)

This will create SQL as given below.

SELECT "posts"."id", "posts"."title", "posts"."description" FROM "posts" WHERE "posts"."user_id" = $1 ORDER BY "posts"."id" [["user_id", 5]

Now let\’s say, we have a change in the requirement and we want to know statuses of all the post published by user with ID = 5.

Without reselect

We will have to unscope current selected arguments and the again apply select with new columns. This can be achieved as given below.

posts = posts.unscope(:select).select(:status)

With reselect

Instead of unscope and select operation, this can be achieve using reselect as given below.

posts = post.reselect(:status)

Both versions mentioned above will create a SQL statement as given below.

 SELECT "posts"."status" FROM "posts" WHERE "posts"."user_id" = $1  [["user_id", 5]]

Thus reselect just a short-hand for unscope and then select operation. Here is the source code for reference.

# File activerecord/lib/active_record/relation/query_methods.rb, line 284
def reselect(*args)
  check_if_method_has_arguments!(:reselect, args)
  spawn.reselect!(*args)
end