DTree Labs

moon indicating dark mode
sun indicating light mode

Rails 6 adds reselect on ActiveRecord Relation

December 04, 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