diff --git a/backend/app/controllers/api/v1/checkins_controller.rb b/backend/app/controllers/api/v1/checkins_controller.rb index 1710c8fc7..901cbc415 100644 --- a/backend/app/controllers/api/v1/checkins_controller.rb +++ b/backend/app/controllers/api/v1/checkins_controller.rb @@ -7,9 +7,10 @@ def index if date.blank? && params.require(:page) render json: current_user.checkins.where(:note.nin => [nil, ""]).order_by(date: :desc).page(params[:page]).per(10) else - render json: current_user.checkins.includes([:harvey_bradshaw_index, :promotion_rate, :conditions, :symptoms, :treatments]).select { |x| - x.date.to_date == Date.parse(date) - } + day = Date.parse(date) + checkins = current_user.checkins.by_date(day.beginning_of_day, day.end_of_day) + # to_a so the criteria is loaded and eager loaded once, not once per serializer pass + render json: checkins.includes([:harvey_bradshaw_index, :promotion_rate, :conditions, :symptoms, :treatments]).to_a end end diff --git a/backend/spec/controllers/api/v1/checkins_controller_spec.rb b/backend/spec/controllers/api/v1/checkins_controller_spec.rb index 03a846906..7f957b776 100644 --- a/backend/spec/controllers/api/v1/checkins_controller_spec.rb +++ b/backend/spec/controllers/api/v1/checkins_controller_spec.rb @@ -22,6 +22,15 @@ returned_checkin = response_body[:checkins][0] expect(Date.parse(returned_checkin[:date])).to eq Date.parse(date) end + + it "filters by date in the database instead of loading every checkin" do + commands = capture_mongo_commands { get :index, params: {date: date} } + + checkin_finds = commands.select { |command| command.command["find"] == "checkins" } + + expect(checkin_finds.size).to eq 1 + expect(checkin_finds.first.command["filter"]["date"].keys).to match_array ["$gte", "$lte"] + end end context "when checkin doesn't exist for the passed date" do it "returns no results" do diff --git a/backend/spec/support/mongo_commands.rb b/backend/spec/support/mongo_commands.rb new file mode 100644 index 000000000..6f3c66659 --- /dev/null +++ b/backend/spec/support/mongo_commands.rb @@ -0,0 +1,39 @@ +# Captures the commands the Mongo driver sends while a block runs, so specs can +# assert that filtering happens in the database rather than in Ruby. +module MongoCommands + class Subscriber + attr_reader :commands + + def initialize + @commands = [] + end + + def started(event) + @commands << event + end + + def succeeded(event) + end + + def failed(event) + end + end + + def capture_mongo_commands + subscriber = Subscriber.new + client = Mongoid.default_client + client.subscribe(Mongo::Monitoring::COMMAND, subscriber) + + begin + yield + ensure + client.unsubscribe(Mongo::Monitoring::COMMAND, subscriber) + end + + subscriber.commands + end +end + +RSpec.configure do |config| + config.include MongoCommands, type: :controller +end