1

I have a rails application where I have following models.

BookingHotel
    has_many :hotel_picture_partners, through: :hotel_pictures
    has_many :booking_hotel_partner_details, dependent: :destroy

BookingHotelPartnerDetail
    belongs_to :booking_hotel

HotelPicturePartner
    belongs_to :hotel_picture, dependent: :destroy

I have a query as follows

@booking_hotel_partner_details = BookingHotelPartnerDetail.unscoped.select(:id, :booking_hotel_id, :partner_booking_hotel_id).includes(booking_hotel: :hotel_picture_partners) 

This puts memory under pressure as it loads all data for included models.

Is there a way I can only load selective fields from booking_hotels & hotel_picture_partners tables ?

Also I want to get an activerecord array as response.

RamanSM
  • 275
  • 3
  • 13
  • Possible duplicate of [Rails 3 - select with Include?](http://stackoverflow.com/questions/4047833/rails-3-select-with-include) – Hasmukh Rathod Aug 17 '16 at 07:47

2 Answers2

1

pluck method loads only attributes, without loading whole models. check it: http://apidock.com/rails/ActiveRecord/Calculations/pluck.

Try to rewrite it like this: BookingHotelPartnerDetail.unscoped.select('booking_hotels.id as bh_id', 'hotel_picture_partners.id as hpp_id').joins(booking_hotel: :hotel_picture_partners)

Andrey Saleba
  • 2,167
  • 4
  • 20
  • 27
0

Your project is probably already pretty far along, but for anyone else wanting this behaviour I've released a patch that filters columns if you have a .select(...) along with .includes(...) or .eager_load(...). It's now included in a data-related gem I maintain, The Brick.

It works by overriding ActiveRecord::Associations::JoinDependency.apply_column_aliases() like this.

In order to enable this selective behaviour, add the special column name :_brick_eager_load as the first entry in your .select(...), which turns on the filtering of columns while the aliases are being built out. Here's an example based on your code:

@booking_hotel_partner_details =
  BookingHotelPartnerDetail.unscoped
                           .includes(booking_hotel: :hotel_picture_partners)
                           .select(:_brick_eager_load, :id, :partner_booking_hotel_id, 'booking_hotel.name', 'hotel_picture_partners.notes')

Feel free to add myraid additional columns from any table as strings in the same way as the last two sample items I put into the .select(...).

Because foreign keys are essential to have everything be properly associated, they are automatically added, so you do not need to include :booking_hotel_id in your select list.

Hope it can save you both query time and some RAM!

Lorin Thwaits
  • 301
  • 1
  • 3