embed poll submissions into poll session

fixes CNVS-13275, CNVS-13297
This commit embeds all submissions when a particular poll session is
requested by authorized users (the creator/teacher of the poll and
relevant poll session.).  It also deletes all submissions and sessions
that belong to a poll when that poll is deleted.

Test plan
Submission embedding
- Create a poll and related poll session
- Create multiple submissions for the poll as students
- As a teacher, you should be able to see the related submissions
  when requesting the poll session via the API

Poll session/submission deletion
- Create a poll and two poll sessions, with two submissions per session
- Delete the poll via the api, it should be deleted successfully

Change-Id: I335f92eb97be095a2ddf6bc730954ed8a14220ef
Reviewed-on: https://gerrit.instructure.com/35456
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Derek DeVries <ddevries@instructure.com>
QA-Review: Caleb Guanzon <cguanzon@instructure.com>
Product-Review: Josh Simpson <jsimpson@instructure.com>
This commit is contained in:
Josh Simpson 2014-05-27 13:20:55 -06:00
parent c1b4b889fa
commit a3a1205e2d
7 changed files with 72 additions and 14 deletions

View File

@ -26,14 +26,25 @@ module Polling
# "required": ["id", "poll_choice"],
# "properties": {
# "id": {
# "description": "The unique identifier for the account role/user assignment.",
# "description": "The unique identifier for the poll submission.",
# "example": 1023,
# "type": "integer"
# },
# "poll_choice_id": {
# "description": "The id of the chosen poll choice for this submission.",
# "example": 55,
# "description": "The unique identifier of the poll choice chosen for this submission.",
# "example": 155,
# "type": "integer"
# },
# "user_id": {
# "description": "the unique identifier of the user who submitted this poll submission.",
# "example": 4555,
# "type": "integer"
# },
# "created_at": {
# "description": "The date and time the poll submission was submitted.",
# "example": "2013-11-07T13:16:18Z",
# "type": "string",
# "format": "date-time"
# }
# }
# }

View File

@ -22,8 +22,8 @@ module Polling
belongs_to :user
has_many :poll_choices, class_name: 'Polling::PollChoice', dependent: :destroy
has_many :poll_submissions, class_name: 'Polling::PollSubmission'
has_many :poll_sessions, class_name: 'Polling::PollSession'
has_many :poll_submissions, class_name: 'Polling::PollSubmission', dependent: :destroy
has_many :poll_sessions, class_name: 'Polling::PollSession', dependent: :destroy
validates_presence_of :question, :user
validates_length_of :question, maximum: 255, allow_nil: true

View File

@ -21,6 +21,7 @@ module Polling
attr_accessible :text, :poll, :is_correct
belongs_to :poll, class_name: 'Polling::Poll'
has_many :poll_submissions, class_name: 'Polling::PollSubmission', dependent: :destroy
validates_presence_of :poll, :text
validates_length_of :text, maximum: 255, allow_nil: true

View File

@ -1,11 +1,16 @@
module Polling
class PollSessionSerializer < Canvas::APISerializer
root :poll_session
attributes :id, :is_published, :has_public_results, :results, :course_id, :course_section_id, :created_at
attributes :id, :is_published, :has_public_results, :results, :course_id, :course_section_id, :created_at, :poll_id, :poll_submissions
def_delegators :object, :results, :poll
# has_many relationships with embedded objects doesn't work, so we override it this way
def poll_submissions
@poll_submissions ||= object.poll_submissions.map do |submission|
Polling::PollSubmissionSerializer.new(submission, controller: @controller, scope: @scope, root: false)
end
end
def filter(keys)
if poll.grants_right?(current_user, session, :update) || object.has_public_results?
student_keys + teacher_keys
@ -17,11 +22,11 @@ module Polling
private
def teacher_keys
[:has_public_results, :results]
[:has_public_results, :results, :poll_submissions]
end
def student_keys
[:id, :is_published, :course_id, :course_section_id, :created_at]
[:id, :is_published, :course_id, :course_section_id, :created_at, :poll_id]
end
end
end

View File

@ -1,7 +1,6 @@
module Polling
class PollSubmissionSerializer < Canvas::APISerializer
root :poll_submission
attributes :id, :poll_choice_id
attributes :id, :poll_session_id, :poll_choice_id, :user_id, :created_at
end
end

View File

@ -95,12 +95,29 @@ describe Polling::PollSessionsController, type: :request do
context "as a teacher" do
it "retrieves the poll session specified even if closed" do
@poll_session.close!
@user = @teacher
json = get_show
poll_json = json['poll_sessions'].first
poll_json['id'].should == @poll_session.id.to_s
poll_json['is_published'].should be_false
end
it "embeds the associated poll submissions" do
choice1 = @poll.poll_choices.create!(text: 'Choice A', is_correct: true)
choice2 = @poll.poll_choices.create!(text: 'Choice B', is_correct: false)
2.times { create_submission(choice1) }
1.times { create_submission(choice2) }
@user = @teacher
json = get_show
poll_session_json = json['poll_sessions'].first
poll_session_json.should have_key('poll_submissions')
poll_session_json['poll_submissions'].size.should == 3
end
it "shows the results of a current poll session" do
choice1 = @poll.poll_choices.create!(text: 'Choice A', is_correct: true)
choice2 = @poll.poll_choices.create!(text: 'Choice B', is_correct: false)
@ -119,6 +136,21 @@ describe Polling::PollSessionsController, type: :request do
end
context "as a student" do
it "doesn't embed the associated poll submissions" do
choice1 = @poll.poll_choices.create!(text: 'Choice A', is_correct: true)
choice2 = @poll.poll_choices.create!(text: 'Choice B', is_correct: false)
2.times { create_submission(choice1) }
1.times { create_submission(choice2) }
student = student_in_course(active_user:true).user
@user = student
json = get_show
json.should_not have_key('poll_submissions')
end
context "when has_public_results is false" do
it "doesn't show the results of a current poll session" do
choice1 = @poll.poll_choices.create!(text: 'Choice A', is_correct: true)
@ -342,6 +374,4 @@ describe Polling::PollSessionsController, type: :request do
end
end
end
end

View File

@ -170,6 +170,16 @@ describe Polling::PollsController, type: :request do
describe 'DELETE destroy' do
before(:each) do
@poll = @teacher.polls.create!(question: 'An Old Title')
@choice = @poll.poll_choices.create!(text: 'Blah')
@session = @poll.poll_sessions.create!(course: @course)
@session.publish!
@student = student_in_course(active_user: true).user
@submission = @session.poll_submissions.create!(
user: @student,
poll: @poll,
poll_choice: @choice
)
end
def delete_destroy
@ -183,6 +193,7 @@ describe Polling::PollsController, type: :request do
context "as a teacher" do
it "deletes a poll successfully" do
@user = @teacher
delete_destroy
response.code.should == '204'
@ -193,6 +204,7 @@ describe Polling::PollsController, type: :request do
choice_a = @poll.poll_choices.create!(text: 'choice a')
choice_b = @poll.poll_choices.create!(text: 'choice b')
@user = @teacher
delete_destroy
response.code.should == '204'
Polling::PollChoice.find_by_id(choice_a.id).should be_nil