add jsonapi pagination to polling and missing documentation

fixes CNVS-13534
This commit adds 2 things.  One is that, when it's requested via the
'Accept' request header with a value of 'application/vnd.api+json', it
will return jsonapi standard pagination.  The other is the addition of
of documentation for the 'results' attribute on poll sessions, and the
'total_results' attribute on polls.

Test plan
1. jsonapi pagination
- As a teacher, and using a header of Accept: application/vnd.api+json
  Test the following endpoints:
  - The polls index endpoint
  - The poll_choices index endpoint
  - The poll_sessions index endpoint
  - The poll_sessions opened endpoint
  - The poll_sessions closed endpoint
  - Each of these endpoints should return the same JSON response, but
    with the addition of a 'meta' attribute that has a 'pagination' key,
    with pagination information.

2. documentation
- The documentation for polls should now include a 'total_results'
  attribute, and the documentation for poll_sessions should include a
  'results' attribute.

Change-Id: I2a16b4d32b3b2a4f2023628b24f9accaecbffcc1
Reviewed-on: https://gerrit.instructure.com/36216
Tested-by: Jenkins <jenkins@instructure.com>
QA-Review: Caleb Guanzon <cguanzon@instructure.com>
Reviewed-by: Derek DeVries <ddevries@instructure.com>
Product-Review: Josh Simpson <jsimpson@instructure.com>
This commit is contained in:
Josh Simpson 2014-06-10 13:54:55 -06:00
parent 7434644311
commit 2f594ea5e3
7 changed files with 176 additions and 41 deletions

View File

@ -72,9 +72,9 @@ module Polling
def index
if authorized_action(@poll, @current_user, :read)
@poll_choices = @poll.poll_choices
@poll_choices = Api.paginate(@poll_choices, self, api_v1_poll_choices_url(@poll))
json, meta = paginate_for(@poll_choices)
render json: serialize_jsonapi(@poll_choices)
render json: serialize_jsonapi(json, meta)
end
end
@ -178,18 +178,30 @@ module Polling
end
protected
def serialize_jsonapi(poll_choices)
def paginate_for(poll_choices)
meta = {}
json = if accepts_jsonapi?
poll_choices, meta = Api.jsonapi_paginate(poll_choices, self, api_v1_poll_choices_url(@poll))
meta[:primaryCollection] = 'poll_choices'
poll_choices
else
Api.paginate(poll_choices, self, api_v1_poll_choices_url(@poll))
end
return json, meta
end
def serialize_jsonapi(poll_choices, meta = {})
poll_choices = Array.wrap(poll_choices)
serialized_set = Canvas::APIArraySerializer.new(poll_choices, {
Canvas::APIArraySerializer.new(poll_choices, {
each_serializer: Polling::PollChoiceSerializer,
controller: self,
root: false,
root: :poll_choices,
meta: meta,
scope: @current_user,
include_root: false
}).as_json
{ poll_choices: serialized_set }
end
end

View File

@ -60,6 +60,11 @@ module Polling
# "example": "2014-01-07T15:16:18Z",
# "type": "string",
# "format": "date-time"
# },
# "results": {
# "description": "The results of the submissions of the poll. Each key is the poll choice id, and the value is the count of submissions.",
# "example": { "144": 10, "145": 3, "146": 27, "147": 8 },
# "type": "object"
# }
# }
# }
@ -83,9 +88,9 @@ module Polling
def index
if authorized_action(@poll, @current_user, :update)
@poll_sessions = @poll.poll_sessions
@poll_sessions = Api.paginate(@poll_sessions, self, api_v1_poll_sessions_url(@poll))
json, meta = paginate_for(@poll_sessions, api_v1_poll_sessions_url(@poll))
render json: serialize_jsonapi(@poll_sessions)
render json: serialize_jsonapi(json, meta)
end
end
@ -243,7 +248,8 @@ module Polling
#
def opened
@poll_sessions = Polling::PollSession.available_for(@current_user).where(is_published: true)
render json: serialize_jsonapi(@poll_sessions)
json, meta = paginate_for(@poll_sessions, api_v1_poll_sessions_opened_url)
render json: serialize_jsonapi(json, meta)
end
# @API List closed poll sessions
@ -258,22 +264,36 @@ module Polling
#
def closed
@poll_sessions = Polling::PollSession.available_for(@current_user).where(is_published: false)
render json: serialize_jsonapi(@poll_sessions)
json, meta = paginate_for(@poll_sessions, api_v1_poll_sessions_closed_url)
render json: serialize_jsonapi(json, meta)
end
protected
def serialize_jsonapi(poll_sessions)
def paginate_for(poll_sessions, api_url="")
meta = {}
json = if accepts_jsonapi?
poll_sessions, meta = Api.jsonapi_paginate(poll_sessions, self, api_url)
meta[:primaryCollection] = 'poll_sessions'
poll_sessions
else
Api.paginate(poll_sessions, self, api_url)
end
return json, meta
end
def serialize_jsonapi(poll_sessions, meta = {})
poll_sessions = Array.wrap(poll_sessions)
serialized_set = Canvas::APIArraySerializer.new(poll_sessions, {
Canvas::APIArraySerializer.new(poll_sessions, {
each_serializer: Polling::PollSessionSerializer,
controller: self,
root: false,
root: :poll_sessions,
meta: meta,
scope: @current_user,
include_root: false
}).as_json
{ poll_sessions: serialized_set }
end
end

View File

@ -108,15 +108,14 @@ module Polling
def serialize_jsonapi(poll_submissions)
poll_submissions = Array.wrap(poll_submissions)
serialized_set = Canvas::APIArraySerializer.new(poll_submissions, {
Canvas::APIArraySerializer.new(poll_submissions, {
each_serializer: Polling::PollSubmissionSerializer,
controller: self,
root: false,
root: :poll_submissions,
meta: {},
scope: @current_user,
include_root: false
}).as_json
{ poll_submissions: serialized_set }
end
end

View File

@ -50,6 +50,11 @@ module Polling
# "description": "The unique identifier for the user that created the poll.",
# "example": 105,
# "type": "integer"
# },
# "total_results": {
# "description": "An aggregate of the results of all associated poll sessions, with the poll choice id as the key, and the aggregated submission count as the value.",
# "example": { "543": 20, "544": 5, "545": 17 },
# "type": "object"
# }
# }
# }
@ -71,9 +76,9 @@ module Polling
#
def index
@polls = @current_user.polls.order('created_at DESC')
@polls = Api.paginate(@polls, self, api_v1_polls_url)
json, meta = paginate_for(@polls)
render json: serialize_jsonapi(@polls)
render json: serialize_jsonapi(json, meta)
end
# @API Get a single poll
@ -166,18 +171,30 @@ module Polling
end
protected
def serialize_jsonapi(polls)
def paginate_for(polls)
meta = {}
json = if accepts_jsonapi?
polls, meta = Api.jsonapi_paginate(polls, self, api_v1_polls_url)
meta[:primaryCollection] = 'polls'
polls
else
Api.paginate(polls, self, api_v1_polls_url)
end
return json, meta
end
def serialize_jsonapi(polls, meta = {})
polls = Array.wrap(polls)
serialized_set = Canvas::APIArraySerializer.new(polls, {
Canvas::APIArraySerializer.new(polls, {
each_serializer: Polling::PollSerializer,
controller: self,
root: false,
root: :polls,
meta: meta,
scope: @current_user,
include_root: false
}).as_json
{ polls: serialized_set }
end
end

View File

@ -33,13 +33,13 @@ describe Polling::PollChoicesController, type: :request do
@poll.poll_choices.create!(text: "Poll Choice 5", is_correct:false, position: 5)
end
def get_index(raw = false, data = {})
def get_index(raw = false, data = {}, headers = {})
helper = method(raw ? :raw_api_call : :api_call)
helper.call(:get,
"/api/v1/polls/#{@poll.id}/poll_choices",
{ controller: 'polling/poll_choices', action: 'index', format: 'json',
poll_id: @poll.id.to_s
}, data)
}, data, headers)
end
it "returns all existing poll choices" do
@ -62,6 +62,20 @@ describe Polling::PollChoicesController, type: :request do
end
it "paginates to the jsonapi standard if requested" do
json = get_index(false, {}, 'Accept' => 'application/vnd.api+json')
poll_choices_json = json['poll_choices']
poll_choices_json.size.should == 5
poll_choices_json.each_with_index do |pc, i|
pc['text'].should == "Poll Choice #{5-i}"
end
json.should have_key('meta')
json['meta'].should have_key('pagination')
json['meta']['primaryCollection'].should == 'poll_choices'
end
context "as a student" do
before(:each) do
student_in_course(:active_all => true, :course => @course)

View File

@ -32,19 +32,19 @@ describe Polling::PollSessionsController, type: :request do
end
end
def get_index(raw = false, data = {})
def get_index(raw = false, data = {}, header = {})
helper = method(raw ? :raw_api_call : :api_call)
helper.call(:get,
"/api/v1/polls/#{@poll.id}/poll_sessions",
{ controller: 'polling/poll_sessions', action: 'index', format: 'json',
poll_id: @poll.id.to_s
}, data)
}, data, header)
end
it "returns all existing poll sessions" do
json = get_index
poll_sessions_json = json['poll_sessions']
session_ids = @poll.poll_sessions.map(&:id)
session_ids = @poll.poll_sessions.pluck(:id)
poll_sessions_json.size.should == 3
poll_sessions_json.each_with_index do |session, i|
@ -52,6 +52,23 @@ describe Polling::PollSessionsController, type: :request do
session['is_published'].should be_false
end
end
it "paginates to the jsonapi standard if requested" do
json = get_index(false, {}, 'Accept' => 'application/vnd.api+json')
poll_sessions_json = json['poll_sessions']
session_ids = @poll.poll_sessions.pluck(:id)
poll_sessions_json.size.should == 3
poll_sessions_json.each_with_index do |session, i|
session_ids.should include(session['id'].to_i)
session['is_published'].should be_false
end
json.should have_key('meta')
json['meta'].should have_key('pagination')
json['meta']['primaryCollection'].should == 'poll_sessions'
end
end
describe 'GET show' do
@ -437,11 +454,11 @@ describe Polling::PollSessionsController, type: :request do
@poll2 = Polling::Poll.create!(user: @teacher2, question: 'Another Test Poll')
end
def get_opened
def get_opened(headers = {})
api_call(:get,
"/api/v1/poll_sessions/opened",
{ controller: 'polling/poll_sessions', action: 'opened', format: 'json' },
{}, {}, {})
{}, headers)
end
it "returns all poll sessions available to the current user that are published" do
@ -475,6 +492,27 @@ describe Polling::PollSessionsController, type: :request do
session_ids.should include(@published.id)
session_ids.should_not include(@wrong_course_section.id)
end
it "paginates to the jsonapi standard if requested" do
@published = @poll1.poll_sessions.create!(course: @course1)
@published.publish!
@unenrolled = @poll2.poll_sessions.create!(course: @course2)
@unenrolled.publish!
@not_published = @poll1.poll_sessions.create!(course: @course1)
student_in_course(active_all: true, course: @course1)
json = get_opened('Accept' => 'application/vnd.api+json')
sessions = json['poll_sessions']
session_ids = sessions.map { |session| session["id"].to_i }
session_ids.should include(@published.id)
session_ids.should_not include(@unenrolled.id)
session_ids.should_not include(@not_published.id)
json.should have_key('meta')
json['meta'].should have_key('pagination')
json['meta']['primaryCollection'].should == 'poll_sessions'
end
end
describe 'GET closed' do
@ -487,11 +525,11 @@ describe Polling::PollSessionsController, type: :request do
@poll2 = Polling::Poll.create!(user: @teacher2, question: 'Another Test Poll')
end
def get_closed
def get_closed(headers = {})
api_call(:get,
"/api/v1/poll_sessions/closed",
{ controller: 'polling/poll_sessions', action: 'closed', format: 'json' },
{}, {}, {})
{}, headers)
end
it "returns all poll sessions available to the current user that are closed" do
@ -526,6 +564,28 @@ describe Polling::PollSessionsController, type: :request do
session_ids.should include(@not_published.id)
session_ids.should_not include(@wrong_course_section.id)
end
end
it "paginates to the jsonapi standard if requested" do
@published = @poll1.poll_sessions.create!(course: @course1)
@published.publish!
@unenrolled = @poll2.poll_sessions.create!(course: @course2)
@unenrolled.close!
@not_published = @poll1.poll_sessions.create!(course: @course1)
@not_published.close!
student_in_course(active_all: true, course: @course1)
json = get_closed('Accept' => 'application/vnd.api+json')
sessions = json['poll_sessions']
session_ids = sessions.map { |session| session["id"].to_i }
session_ids.should include(@not_published.id)
session_ids.should_not include(@unenrolled.id)
session_ids.should_not include(@published.id)
json.should have_key('meta')
json['meta'].should have_key('pagination')
json['meta']['primaryCollection'].should == 'poll_sessions'
end
end
end

View File

@ -30,12 +30,13 @@ describe Polling::PollsController, type: :request do
end
end
def get_index(raw = false, data = {})
def get_index(raw = false, data = {}, headers = {})
helper = method(raw ? :raw_api_call : :api_call)
helper.call(:get,
"/api/v1/polls",
{ controller: 'polling/polls', action: 'index', format: 'json' },
data)
data,
headers)
end
it "returns all existing polls" do
@ -48,6 +49,20 @@ describe Polling::PollsController, type: :request do
end
end
it "paginates to the jsonapi standard if requested" do
json = get_index(false, {}, 'Accept' => 'application/vnd.api+json')
poll_json = json['polls']
poll_json.size.should == 5
poll_json.each_with_index do |poll, i|
poll['question'].should == "Example Poll #{5-i}"
end
json.should have_key('meta')
json['meta'].should have_key('pagination')
json['meta']['primaryCollection'].should == 'polls'
end
context "as a site admin" do
it "you can view polls you have created" do
Account.site_admin.add_user(@teacher)
@ -251,7 +266,5 @@ describe Polling::PollsController, type: :request do
Polling::Poll.find_by_id(@poll.id).should == @poll
end
end
end
end