allow the quiz submission users endpoint to sideload quiz submissions

Test plan:
  - As a teacher in a course, create a quiz.
  - Have some students take the quiz, and some students not take the
    quiz.
  - Query
    '/api/v1/courses/:course_id/quizzes/:quiz_id/submission_users?include[]=quiz_submissions'
  - You should see quiz submission data in "quiz_submissions" in the
    json root with the quiz submissions for each user.

fixes CNVS-12896

Change-Id: Ia5ca15c07c97c009267fc52dcd02c61355fcfd2f
Reviewed-on: https://gerrit.instructure.com/34422
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Jason Madsen <jmadsen@instructure.com>
Reviewed-by: Derek DeVries <ddevries@instructure.com>
QA-Review: Caleb Guanzon <cguanzon@instructure.com>
Product-Review: Stanley Stuart <stanley@instructure.com>
This commit is contained in:
Stanley Stuart 2014-05-06 15:05:52 -05:00
parent 7722732692
commit f3b9511d71
5 changed files with 151 additions and 14 deletions

View File

@ -26,6 +26,11 @@ module Quizzes
# who have not submitted the quiz. If not present, returns all students for
# the course.
#
# @argument includes [Optional, array]
# Optional list of resources to include with the response. May include
# a string of the name of the resource. Possible values are:
# "quiz_submissions".
#
# @returns QuizSubmissionUserList
#
# @model QuizSubmissionUserList
@ -81,16 +86,30 @@ module Quizzes
# }
def index
return unless user_has_teacher_level_access?
@users = if submitted_param?
@users = submitted? ? submitted_users : unsubmitted_users
else
@users = user_finder.all_students
@users = index_users
includes = Array(params[:include])
@users, meta = Api.jsonapi_paginate(@users, self, index_base_url, params)
if includes.include? 'quiz_submissions'
quiz_submissions = QuizSubmission.where(user_id: @users.to_a, quiz_id: @quiz).index_by(&:user_id)
end
users_json = Canvas::APIArraySerializer.new(@users, {
quiz: @quiz,
root: :users,
meta: meta,
quiz_submissions: quiz_submissions,
includes: includes,
controller: self,
each_serializer: Quizzes::QuizSubmissionUserSerializer
})
render json: users_json.as_json
end
@users, meta = Api.jsonapi_paginate(@users, self, index_base_url, page: params[:page])
users_json = @users.map { |user| user_json(user, @current_user, session) }
render json: { meta: meta, users: users_json }
def index_users
if submitted_param?
submitted? ? submitted_users : unsubmitted_users
else
user_finder.all_students
end
end
# @API Send a message to unsubmitted or submitted users for the quiz

View File

@ -4,13 +4,14 @@ module Canvas
def initialize(object, options={})
super(object, options)
@options = options
@controller = options.fetch(:controller)
@sideloads = options.fetch(:includes, [])
end
def serializer_for(item)
serializer_class = @each_serializer || ActiveModel::Serializer.serializer_for(item) || ActiveModel::DefaultSerializer
serializer_class.new(item, scope: scope, controller: @controller, includes: @sideloads)
serializer_class.new(item, @options)
end
def serializable_object

View File

@ -0,0 +1,35 @@
# Copyright (C) 2014 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
module Quizzes
class QuizSubmissionSerializer < Canvas::APISerializer
include Api::V1::QuizSubmission
root :quiz_submission
attributes :id
def_delegators :@controller,
:course_quiz_quiz_submission_url
def serializable_object(options={})
return super unless object
hash = quiz_submission_json(object, object.quiz, current_user, session, context)
hash[:id] = hash[:id].to_s unless hash[:id].nil?
@wrap_in_array ? [hash] : hash
end
end
end

View File

@ -0,0 +1,70 @@
# Copyright (C) 2014 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
module Quizzes
class QuizSubmissionUserSerializer < Canvas::APISerializer
include Api::V1::User
root :user
attr_reader :quiz, :quiz_submissions
# For Api::V1::User#user_json
def_delegators :@controller,
:service_enabled?
attributes :id
has_one :quiz_submission, include: true, embed: :ids, key: :quiz_submission, embed_in_root: true, serializer: Quizzes::QuizSubmissionSerializer
LEGACY_INSTANCE_VARIABLES = %w[
current_user
domain_root_account
].freeze
def quiz_submission
quiz_submissions[object.id]
end
def initialize(object, options)
super(object, options)
@quiz = options.fetch(:quiz)
# QuizSubmissions should be preloaded by the controller and provided to
# the serializer so we don't have a bunch of N+1 queries
@quiz_submissions = options[:quiz_submissions] || []
# For Api::V1::User#user_json
LEGACY_INSTANCE_VARIABLES.each do |ivar|
instance_variable_set "@#{ivar}", @controller.instance_variable_get("@#{ivar}")
end
end
def filter(keys)
keys.select do |key|
case key
when :quiz_submission then sideloads.include?('quiz_submissions')
else true
end
end
end
def serializable_object(options={})
super.merge!(
user_json(object, current_user, session, sideloads)
)
end
end
end

View File

@ -95,7 +95,7 @@ describe Quizzes::QuizSubmissionUsersController, type: :request do
@user = @teacher
json = get_submitted_users(submitted: true)
response.should be_success
json['users'].first['id'].should == @student.id
json['users'].first['id'].should == @student.id.to_s
end
it "allows teachers to see unsubmitted students with ?submitted=false" do
@ -107,8 +107,8 @@ describe Quizzes::QuizSubmissionUsersController, type: :request do
json = get_submitted_users(submitted: false)
response.should be_success
user_ids = json['users'].map { |h| h['id'] }
user_ids.should_not include @student_frd.id
user_ids.should include @student.id
user_ids.should_not include @student_frd.id.to_s
user_ids.should include @student.id.to_s
end
it "allows teachers to see all students for quiz when submitted parameter not passed" do
@ -120,8 +120,20 @@ describe Quizzes::QuizSubmissionUsersController, type: :request do
json = get_submitted_users
response.should be_success
user_ids = json['users'].map { |h| h['id'] }
user_ids.should include @student_frd.id
user_ids.should include @student.id
user_ids.should include @student_frd.id.to_s
user_ids.should include @student.id.to_s
end
it "will sideload quiz_submissions" do
course_with_student(active_all: true, course: @course)
@student_frd = @student
quiz_with_graded_submission([], course: @course, user: @student_frd)
course_with_student(active_all: true, course: @course)
@user = @teacher
json = get_submitted_users(include: ['quiz_submissions'])
response.should be_success
json['quiz_submissions'].first.with_indifferent_access[:id].should == @quiz_submission.id.to_s
json['quiz_submissions'].length.should == 1
end
end
end