improve outcome results controller performance for large numbers

avoids large queries when the course has a lot of outcomes

test plan:
* regression test outcome results api

closes #CNVS-12716

Change-Id: I9752ebcc605f52eaee81d934308a7b0850032abe
Reviewed-on: https://gerrit.instructure.com/62260
Tested-by: Jenkins
Reviewed-by: Jeremy Stanley <jeremy@instructure.com>
QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com>
Product-Review: James Williams  <jamesw@instructure.com>
This commit is contained in:
James Williams 2015-09-01 10:59:06 -06:00
parent df632b6020
commit 88b5e8e101
2 changed files with 28 additions and 13 deletions

View File

@ -406,20 +406,32 @@ class OutcomeResultsController < ApplicationController
end
def require_outcomes
reject! "can't filter by both outcome_ids and outcome_group_id" if params[:outcome_ids] && params[:outcome_group_id]
@outcome_groups = @context.learning_outcome_groups
outcome_group_ids = @outcome_groups.pluck(:id)
@outcome_links = ContentTag.learning_outcome_links.active.where(associated_asset_id: outcome_group_ids).preload(:learning_outcome_content)
reject! "can't filter by both outcome_ids and outcome_group_id" if params[:outcome_ids] && params[:outcome_group_id]
if params[:outcome_ids]
outcome_ids = Api.value_to_array(params[:outcome_ids]).map(&:to_i).uniq
@outcomes = @outcome_links.map(&:learning_outcome_content).select{ |outcome| outcome_ids.include?(outcome.id) }
reject! "can only include id's of outcomes in the outcome context" if @outcomes.count != outcome_ids.count
elsif params[:outcome_group_id]
if params[:outcome_group_id]
group_id = params[:outcome_group_id].to_i
reject! "can only include an outcome group id in the outcome context" unless outcome_group_ids.include?(group_id)
@outcomes = @outcome_links.where(associated_asset_id: group_id).map(&:learning_outcome_content)
else
@outcome_links = ContentTag.learning_outcome_links.active.where(associated_asset_id: group_id).preload(:learning_outcome_content)
@outcomes = @outcome_links.map(&:learning_outcome_content)
else
@outcome_links = []
outcome_group_ids.each_slice(100) do |outcome_group_ids_slice|
@outcome_links += ContentTag.learning_outcome_links.active.where(associated_asset_id: outcome_group_ids_slice)
end
@outcome_links.each_slice(100) do |outcome_links_slice|
ActiveRecord::Associations::Preloader.new(outcome_links_slice, :learning_outcome_content).run
end
if params[:outcome_ids]
outcome_ids = Api.value_to_array(params[:outcome_ids]).map(&:to_i).uniq
@outcomes = @outcome_links.map(&:learning_outcome_content).select{ |outcome| outcome_ids.include?(outcome.id) }
reject! "can only include id's of outcomes in the outcome context" if @outcomes.count != outcome_ids.count
else
@outcomes = @outcome_links.map(&:learning_outcome_content)
end
end
end

View File

@ -60,10 +60,13 @@ module Api::V1::OutcomeResults
#
# Returns a Hash containing serialized outcomes.
def outcome_results_include_outcomes_json(outcomes)
ActiveRecord::Associations::Preloader.new(outcomes, [:context, :alignments]).run
assessed_outcomes = LearningOutcomeResult.uniq
.where(learning_outcome_id: outcomes.map(&:id))
.pluck(:learning_outcome_id)
outcomes.each_slice(50).each do |outcomes_slice|
ActiveRecord::Associations::Preloader.new(outcomes_slice, [:context, :alignments]).run
end
assessed_outcomes = []
outcomes.map(&:id).each_slice(100) do |outcome_ids|
assessed_outcomes += LearningOutcomeResult.uniq.where(learning_outcome_id: outcome_ids).pluck(:learning_outcome_id)
end
outcomes.map do |o|
hash = outcome_json(o, @current_user, session, assessed_outcomes: assessed_outcomes)
hash.merge!(alignments: o.alignments.map(&:content_asset_string))