Rails 6 adds reselect on ActiveRecord Relation

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

Leave a Comment

Your email address will not be published. Required fields are marked *