api for retrieving submissions by student, refs #4156

Change-Id: Iffa4527ff11fcbb0ca798b1bf3c7572826648174
Reviewed-on: https://gerrit.instructure.com/2983
Reviewed-by: Zach Wily <zach@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
This commit is contained in:
Brian Palmer 2011-04-05 13:33:44 -06:00
parent b1a9f2aa78
commit 3cf394644e
3 changed files with 107 additions and 20 deletions

View File

@ -37,7 +37,39 @@ class SubmissionsApiController < ApplicationController
includes = Array(params[:include])
result = @submissions.map { |s| submission_json(s, includes) }
result = @submissions.map { |s| submission_json(s, @assignment, includes) }
render :json => result.to_json
end
end
# @API
#
# Get all existing submissions for a given set of students and assignments.
#
# @argument student_ids[] List of student ids to return submissions for. At least one is required.
# @argument assignment_ids[] List of assignments to return submissions for. If none are given, submissions for all assignments are returned.
# @argument include[] ["submission_history"|"submission_comments"|"rubric_assessment"] Associations to include with the group.
def for_students
if authorized_action(@context, @current_user, :manage_grades)
student_ids = Array(params[:student_ids]).map(&:to_i)
raise ActiveRecord::RecordNotFound if student_ids.blank?
assignment_ids = Array(params[:assignment_ids]).map(&:to_i)
scope = @context.submissions.scoped(:include => :assignment)
if assignment_ids.present?
@submissions = scope.all(
:conditions => {:user_id => student_ids, :assignment_id => assignment_ids})
else
@submissions = scope.all(
:conditions => {:user_id => student_ids})
end
includes = Array(params[:include])
result = @submissions.map { |s| submission_json(s, s.assignment, includes) }
render :json => result.to_json
end
@ -54,7 +86,7 @@ class SubmissionsApiController < ApplicationController
@submission = @assignment.submissions.find_by_user_id(params[:id]) or raise ActiveRecord::RecordNotFound
includes = Array(params[:include])
render :json => submission_json(@submission, includes).to_json
render :json => submission_json(@submission, @assignment, includes).to_json
end
end
@ -155,7 +187,7 @@ class SubmissionsApiController < ApplicationController
# fix this at some point.
@submission.reload
render :json => submission_json(@submission, %w(submission_comments)).to_json
render :json => submission_json(@submission, @assignment, %w(submission_comments)).to_json
end
end
@ -163,13 +195,13 @@ class SubmissionsApiController < ApplicationController
# We might want to make a Helper that holds all these methods to convert AR
# objects to the API json formatting.
def submission_json(submission, includes = [])
hash = submission_attempt_json(submission)
def submission_json(submission, assignment, includes = [])
hash = submission_attempt_json(submission, assignment)
if includes.include?("submission_history")
hash['submission_history'] = []
submission.submission_history.each_with_index do |ver, idx|
hash['submission_history'] << submission_attempt_json(ver, idx)
hash['submission_history'] << submission_attempt_json(ver, assignment, idx)
end
end
@ -183,7 +215,7 @@ class SubmissionsApiController < ApplicationController
sc.media_comment_type)
end
sc_hash['attachments'] = sc.attachments.map do |a|
attachment_json(a, {:comment_id => sc.id, :id => submission.user_id})
attachment_json(a, assignment, {:comment_id => sc.id, :id => submission.user_id})
end unless sc.attachments.blank?
sc_hash
end
@ -198,15 +230,15 @@ class SubmissionsApiController < ApplicationController
hash
end
SUBMISSION_JSON_FIELDS = %w(user_id url score grade attempt submission_type submitted_at body)
SUBMISSION_JSON_FIELDS = %w(user_id url score grade attempt submission_type submitted_at body assignment_id)
def submission_attempt_json(attempt, version_idx = nil)
def submission_attempt_json(attempt, assignment, version_idx = nil)
hash = attempt.as_json(
:include_root => false,
:only => SUBMISSION_JSON_FIELDS)
hash['preview_url'] = course_assignment_submission_url(
@context, @assignment, attempt[:user_id], 'preview' => '1',
@context, assignment, attempt[:user_id], 'preview' => '1',
'version' => version_idx)
unless attempt.media_comment_id.blank?
@ -216,19 +248,19 @@ class SubmissionsApiController < ApplicationController
attachments = attempt.versioned_attachments.dup
attachments << attempt.attachment if attempt.attachment && attempt.attachment.context_type == 'Submission' && attempt.attachment.context_id == attempt.id
hash['attachments'] = attachments.map do |attachment|
attachment_json(attachment, :id => attempt.user_id)
attachment_json(attachment, assignment, :id => attempt.user_id)
end unless attachments.blank?
# include the discussion topic entries
if @assignment.submission_types =~ /discussion_topic/ &&
@assignment.discussion_topic
if assignment.submission_types =~ /discussion_topic/ &&
assignment.discussion_topic
# group assignments will have a child topic for each group.
# it's also possible the student posted in the main topic, as well as the
# individual group one. so we search far and wide for all student entries.
if @assignment.group_category
entries = @assignment.discussion_topic.child_topics.map {|t| t.discussion_entries.active.for_user(attempt.user_id) }.flatten.sort_by{|e| e.created_at}
if assignment.group_category
entries = assignment.discussion_topic.child_topics.map {|t| t.discussion_entries.active.for_user(attempt.user_id) }.flatten.sort_by{|e| e.created_at}
else
entries = @assignment.discussion_topic.discussion_entries.active.for_user(attempt.user_id)
entries = assignment.discussion_topic.discussion_entries.active.for_user(attempt.user_id)
end
hash['discussion_entries'] = entries.map do |entry|
ehash = entry.as_json(
@ -237,7 +269,7 @@ class SubmissionsApiController < ApplicationController
)
attachments = (entry.attachments.dup + [entry.attachment]).compact
ehash['attachments'] = attachments.map do |attachment|
attachment_json(attachment, :id => attempt.user_id)
attachment_json(attachment, assignment, :id => attempt.user_id)
end unless attachments.blank?
ehash
end
@ -246,12 +278,13 @@ class SubmissionsApiController < ApplicationController
hash
end
def attachment_json(attachment, url_params = {})
def attachment_json(attachment, assignment, url_params = {})
url = case attachment.context_type
when "Course"
course_file_download_url(url_params.merge(:file_id => attachment.id, :id => nil))
else
course_assignment_submission_url(url_params.merge(:download => attachment.id))
course_assignment_submission_url(@context, assignment,
url_params.merge(:download => attachment.id))
end
{
'content-type' => attachment.content_type,

View File

@ -608,8 +608,9 @@ ActionController::Routing::Routes.draw do |map|
# API routes
ApiRouteSet.new(map, "/api/v1") do |api|
api.resources :courses,
:name_prefix => "api_v1_",
:only => %w(index) do |course|
course.api_students 'students.:format',
course.students 'students.:format',
:controller => 'courses', :action => 'students',
:conditions => { :method => :get }
course.resources :assignments,
@ -621,6 +622,9 @@ ActionController::Routing::Routes.draw do |map|
end
course.resources :assignment_groups,
:only => %w(index)
course.student_submissions 'students/submissions.:format',
:controller => 'submissions_api', :action => 'for_students',
:conditions => { :method => :get }
end
end

View File

@ -147,6 +147,7 @@ describe SubmissionsApiController, :type => :integration do
[{"grade"=>"A-",
"prior"=>nil,
"body"=>"test!",
"assignment_id" => a1.id,
"submitted_at"=>"1970-01-01T03:00:00Z",
"preview_url" => "http://www.example.com/courses/#{@course.id}/assignments/#{a1.id}/submissions/#{student1.id}?preview=1",
"attachments" =>
@ -160,6 +161,7 @@ describe SubmissionsApiController, :type => :integration do
[{"grade"=>nil,
"prior"=>nil,
"body"=>"test!",
"assignment_id" => a1.id,
"submitted_at"=>"1970-01-01T01:00:00Z",
"attempt"=>1,
"url"=>nil,
@ -170,6 +172,7 @@ describe SubmissionsApiController, :type => :integration do
"preview_url" => "http://www.example.com/courses/#{@course.id}/assignments/#{a1.id}/submissions/#{student1.id}?preview=1&version=0",
"score"=>nil},
{"grade"=>nil,
"assignment_id" => a1.id,
"media_comment" =>
{ "content-type" => "video/mp4",
"url" => "http://www.example.com/courses/#{@course.id}/media_download?entryId=54321&redirect=1&type=mp4" },
@ -185,6 +188,7 @@ describe SubmissionsApiController, :type => :integration do
"preview_url" => "http://www.example.com/courses/#{@course.id}/assignments/#{a1.id}/submissions/#{student1.id}?preview=1&version=1",
"score"=>nil},
{"grade"=>"A-",
"assignment_id" => a1.id,
"media_comment" =>
{ "content-type" => "video/mp4",
"url" => "http://www.example.com/courses/#{@course.id}/media_download?entryId=54321&redirect=1&type=mp4" },
@ -226,12 +230,14 @@ describe SubmissionsApiController, :type => :integration do
"url" => "http://www.example.com/courses/#{@course.id}/media_download?entryId=54321&redirect=1&type=mp4" },
"score"=>13.5},
{"grade"=>"F",
"assignment_id" => a1.id,
"prior"=>nil,
"body"=>nil,
"preview_url" => "http://www.example.com/courses/#{@course.id}/assignments/#{a1.id}/submissions/#{student2.id}?preview=1",
"submitted_at"=>"1970-01-01T04:00:00Z",
"submission_history"=>
[{"grade"=>"F",
"assignment_id" => a1.id,
"prior"=>nil,
"body"=>nil,
"submitted_at"=>"1970-01-01T04:00:00Z",
@ -267,6 +273,50 @@ describe SubmissionsApiController, :type => :integration do
json.should == res
end
it "should return all submissions for a student" do
student1 = user(:active_all => true)
student2 = user(:active_all => true)
course_with_teacher_logged_in(:active_all => true)
@course.enroll_student(student1).accept!
@course.enroll_student(student2).accept!
a1 = @course.assignments.create!(:title => 'assignment1', :grading_type => 'letter_grade', :points_possible => 15)
a2 = @course.assignments.create!(:title => 'assignment2', :grading_type => 'letter_grade', :points_possible => 25)
submit_homework(a1, student1)
submit_homework(a2, student1)
submit_homework(a1, student2)
json = api_call(:get,
"/api/v1/courses/#{@course.id}/students/submissions.json",
{ :controller => 'submissions_api', :action => 'for_students',
:format => 'json', :course_id => @course.to_param },
{ :student_ids => [student1.to_param] })
json.size.should == 2
json.all? { |submission| submission['user_id'].should == student1.id }.should be_true
json = api_call(:get,
"/api/v1/courses/#{@course.id}/students/submissions.json",
{ :controller => 'submissions_api', :action => 'for_students',
:format => 'json', :course_id => @course.to_param },
{ :student_ids => [student1.to_param, student2.to_param] })
json.size.should == 3
json = api_call(:get,
"/api/v1/courses/#{@course.id}/students/submissions.json",
{ :controller => 'submissions_api', :action => 'for_students',
:format => 'json', :course_id => @course.to_param },
{ :student_ids => [student1.to_param, student2.to_param],
:assignment_ids => [a1.to_param] })
json.size.should == 2
json.all? { |submission| submission['assignment_id'].should == a1.id }.should be_true
end
it "should allow grading an uncreated submission" do
student = user(:active_all => true)
course_with_teacher_logged_in(:active_all => true)