0

how to avoid calling .all from this code? since .all will be load all the items to memory and slow

I've tried to combine them but the code is not really that DRY

companies_controller.rb

  def index
    if params[:search].present?
      @companies = Company.where("name ilike ?", "%#{params[:search]}%")
    else
      @companies = Company.all
    end

    if params[:page].present? && params[:per_page].present?
      @companies = @companies.page(params[:page]).per(params[:per_page])
    elsif params[:page].present?
      @companies = @companies.page(params[:page])
    else
      @companies = @companies.page
    end
  end
buncis
  • 2,148
  • 1
  • 23
  • 25
  • It looks like you want to display all the companies if there is no search term? What do you want to happen when params[:search] isn't present? – Mark Dec 05 '19 at 18:14
  • yeah that is right, but still applying the pagination – buncis Dec 05 '19 at 18:15
  • apparently `.all` will not put all the things immediately into a memory more https://stackoverflow.com/questions/48086269/rails-4-how-can-i-prevent-loading-all-database-records-before-a-call-to-model-a – buncis Dec 05 '19 at 18:53

2 Answers2

2

What about something like this?

def index
  scope = Company.all

  scope = scope.where("name ilike ?", "%#{params[:search]}%") if params[:search].present?
  scope = scope.per(params[:per_page])                        if params[:per_page].present?

  scope.page(params[:page])
end

Note: it is safe to do page(params[:page]) even when params[:page] is blank because Kaminari is able to handle that internally.

Btw: all will not load all the items to memory. It just returns an ActiveRecord::Relation that can return all records. But it will not because you chain more scopes (e.g. page) to it later on.

spickermann
  • 100,941
  • 9
  • 101
  • 131
  • yeah I just test it .all will not load it all into memory, and this answer also said that https://stackoverflow.com/questions/48086269/rails-4-how-can-i-prevent-loading-all-database-records-before-a-call-to-model-a – buncis Dec 05 '19 at 18:49
1

Assuming you're using Kaminari, then you just need to do what you said in your title and take off the all, Kaminari comes with the class methods you use so you can call it directly on the class:

def index
  if params[:search].present?
    @companies = Company.where("name ilike ?", "%#{params[:search]}%")
  else
    @companies = Company
  end

  if params[:page].present? && params[:per_page].present?
    @companies = @companies.page(params[:page]).per(params[:per_page])
  elsif params[:page].present?
    @companies = @companies.page(params[:page])
  else
    @companies = @companies.page
  end
end
Mark
  • 6,112
  • 4
  • 21
  • 46