use defined discussion formats in assignment and submission apis

fixes #6560

The assignment and submission apis were written before the discussion
api, and the response formats diverged. This merges the two formats so
that all apis return the same data structures.

Also, removed the attachments relation from DiscussionEntry, it's cruft.
We have to continue returning the attachments array in the json for now,
for backwards compatibility, since it includes the .attachment field as
well.

test plan: API calls to read discussion assignments and their
submissions should now include the full json response data, see the api
documentation for the discussions api.

Change-Id: Ib394d7e5c3fcf261adb8663470c6822fe2476b03
Reviewed-on: https://gerrit.instructure.com/7395
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Bracken Mosbacker <bracken@instructure.com>
This commit is contained in:
Brian Palmer 2011-12-09 14:17:39 -07:00
parent 17c07f3ea9
commit 032a317cf1
9 changed files with 69 additions and 43 deletions

View File

@ -87,9 +87,14 @@ class DiscussionTopicsApiController < ApplicationController
# @response_field created_at The creation time of the entry, in ISO8601
# format.
#
# @response_field updated_at The updated time of the entry, in ISO8601 format.
#
# @response_field attachment JSON representation of the attachment for the
# entry, if any. Present only if there is an attachment.
#
# @response_field attachments *Deprecated*. Same as attachment, but returned
# as a one-element array. Present only if there is an attachment.
#
# @response_field recent_replies The 10 most recent replies for the entry,
# newest first. Present only if there is at least one reply.
#

View File

@ -47,6 +47,7 @@ class DiscussionTopicsController < ApplicationController
# @response_field title The title of the topic
# @response_field topic_children An array of topic_ids for the group discussions the user is a part of
# @response_field user_name The username of the creator
# @response_field url The URL to the discussion topic in canvas
#
# @example_response
# [
@ -86,7 +87,7 @@ class DiscussionTopicsController < ApplicationController
format.html
format.json do
if api_request?
render :json => discussion_topic_api_json(@topics, @context, @current_user, session)
render :json => discussion_topics_api_json(@topics, @context, @current_user, session)
else
render :json => @topics.to_json(:methods => [:user_name, :discussion_subentry_count], :permissions => {:user => @current_user, :session => session })
end

View File

@ -30,7 +30,6 @@ class DiscussionEntry < ActiveRecord::Base
belongs_to :user
belongs_to :attachment
belongs_to :editor, :class_name => 'User'
has_many :attachments, :as => :context
has_one :external_feed_entry, :as => :asset
before_create :infer_parent_id

View File

@ -18,6 +18,7 @@
module Api::V1::Assignment
include Api::V1::Json
include Api::V1::DiscussionTopics
def assignment_json(assignment, user, session, includes = [], show_admin_fields = false)
# no includes supported right now
@ -55,13 +56,7 @@ module Api::V1::Assignment
end if assignment.rubric
if assignment.discussion_topic
hash['discussion_topic'] = {
'id' => assignment.discussion_topic.id,
'url' => named_context_url(assignment.context,
:context_discussion_topic_url,
assignment.discussion_topic,
:include_host => true)
}
hash['discussion_topic'] = discussion_topic_api_json(assignment.discussion_topic, assignment.discussion_topic.context, user, session)
end
hash

View File

@ -19,38 +19,45 @@
module Api::V1::DiscussionTopics
include Api::V1::Json
def discussion_topic_api_json(topics, context, user, session)
def discussion_topics_api_json(topics, context, user, session)
topics.map do |topic|
discussion_topic_api_json(topic, context, user, session)
end
end
attachments = []
if topic.attachment
attachments << attachment_json(topic.attachment)
end
def discussion_topic_api_json(topic, context, user, session)
attachments = []
if topic.attachment
attachments << attachment_json(topic.attachment)
end
url = nil
if topic.podcast_enabled
code = @context_enrollment ? @context_enrollment.feed_code : @context.feed_code
url = feeds_topic_format_path(topic.id, code, :rss)
end
url = nil
if topic.podcast_enabled
code = @context_enrollment ? @context_enrollment.feed_code : @context.feed_code
url = feeds_topic_format_path(topic.id, code, :rss)
end
children = topic.child_topics.scoped(:select => 'id').map(&:id)
children = topic.child_topics.scoped(:select => 'id').map(&:id)
api_json(topic, user, session,
:only => %w(id title assignment_id delayed_post_at last_reply_at posted_at require_initial_post root_topic_id),
:methods => [:user_name, :discussion_subentry_count]
).tap do |json|
json[:message] = api_user_content(topic.message, context)
json.merge! :podcast_url => url,
:topic_children => children,
:attachments => attachments
end
api_json(topic, user, session,
:only => %w(id title assignment_id delayed_post_at last_reply_at posted_at require_initial_post root_topic_id),
:methods => [:user_name, :discussion_subentry_count]
).tap do |json|
json.merge! :message => api_user_content(topic.message, context),
:podcast_url => url,
:topic_children => children,
:attachments => attachments,
:url => named_context_url(context,
:context_discussion_topic_url,
topic,
:include_host => true)
end
end
def discussion_entry_api_json(entries, context, user, session)
entries.map do |entry|
json = api_json(entry, user, session,
:only => %w(id user_id created_at),
:only => %w(id user_id created_at updated_at),
:methods => [:user_name, :discussion_subentry_count])
json[:message] = api_user_content(entry.message, context)
if entry.parent_id.zero?
@ -60,6 +67,8 @@ module Api::V1::DiscussionTopics
json[:has_more_replies] = replies.size > 10
end
json[:attachment] = attachment_json(entry.attachment) if entry.attachment
# this is for backwards compatibility, and can go away if we make an api v2
json[:attachments] = [attachment_json(entry.attachment)] if entry.attachment
end
json
end

View File

@ -19,6 +19,7 @@
module Api::V1::Submission
include Api::V1::Json
include Api::V1::Assignment
include Api::V1::DiscussionTopics
def submission_json(submission, assignment, user, session, context = nil, includes = [])
context ||= assignment.context
@ -117,17 +118,7 @@ module Api::V1::Submission
else
entries = assignment.discussion_topic.discussion_entries.active.for_user(attempt.user_id)
end
hash['discussion_entries'] = entries.map do |entry|
ehash = entry.as_json(
:include_root => false,
:only => %w(message user_id created_at updated_at)
)
attachments = (entry.attachments.dup + [entry.attachment]).compact
ehash['attachments'] = attachments.map do |attachment|
attachment_json(attachment)
end.compact unless attachments.blank?
ehash
end
hash['discussion_entries'] = discussion_entry_api_json(entries, assignment.discussion_topic.context, user, session)
end
hash

View File

@ -214,8 +214,23 @@ describe AssignmentsApiController, :type => :integration do
{ :controller => 'assignments_api', :action => 'show',
:format => 'json', :course_id => @course.id.to_s,
:id => @assignment.id.to_s, })
json['discussion_topic']['id'].should == @topic.id
json['discussion_topic']['url'].should == "http://www.example.com/courses/#{@course.id}/discussion_topics/#{@topic.id}"
json['discussion_topic'].should == {
'id' => @topic.id,
'title' => 'assignment1',
'message' => nil,
'posted_at' => @topic.posted_at.as_json,
'last_reply_at' => @topic.last_reply_at.as_json,
'require_initial_post' => nil,
'discussion_subentry_count' => 0,
'assignment_id' => @assignment.id,
'delayed_post_at' => nil,
'user_name' => @topic.user_name,
'topic_children' => [],
'root_topic_id' => @topic.root_topic_id,
'podcast_url' => nil,
'url' => "http://www.example.com/courses/#{@course.id}/discussion_topics/#{@topic.id}",
'attachments' => [],
}
end
it "should return the mute status of the assignment" do

View File

@ -46,6 +46,7 @@ describe DiscussionTopicsController, :type => :integration do
"message"=>"<p>content here</p>",
"posted_at"=>@topic.posted_at.as_json,
"root_topic_id"=>nil,
"url" => "http://www.example.com/courses/#{@course.id}/discussion_topics/#{@topic.id}",
"attachments"=>[{"content-type"=>"unknown/unknown",
"url"=>"http://www.example.com/files/#{attachment.id}/download?verifier=#{attachment.uuid}",
"filename"=>"content.txt",
@ -106,6 +107,7 @@ describe DiscussionTopicsController, :type => :integration do
"user_name"=>"User Name",
"last_reply_at"=>gtopic.last_reply_at.as_json,
"message"=>"<p>content here</p>",
"url" => "http://www.example.com/groups/#{group.id}/discussion_topics/#{gtopic.id}",
"attachments"=>
[{"content-type"=>"unknown/unknown",
"url"=>"http://www.example.com/files/#{attachment.id}/download?verifier=#{attachment.uuid}",
@ -177,6 +179,7 @@ describe DiscussionTopicsController, :type => :integration do
"user_name" => @user.name,
"message" => @message,
"created_at" => @entry.created_at.utc.iso8601,
"updated_at" => @entry.updated_at.as_json,
}
end

View File

@ -238,16 +238,20 @@ describe SubmissionsApiController, :type => :integration do
json['discussion_entries'].sort_by { |h| h['user_id'] }.should ==
[{
'id' => se1.id,
'message' => 'sub 1',
'user_id' => @student.id,
'created_at' => se1.created_at.as_json,
'updated_at' => se1.updated_at.as_json,
'user_name' => 'User',
},
{
'id' => se2.id,
'message' => 'student 1',
'user_id' => @student.id,
'created_at' => se2.created_at.as_json,
'updated_at' => se2.updated_at.as_json,
'user_name' => 'User',
}].sort_by { |h| h['user_id'] }
# don't include discussion entries if response_fields limits the response
@ -295,14 +299,18 @@ describe SubmissionsApiController, :type => :integration do
json['discussion_entries'].sort_by { |h| h['user_id'] }.should ==
[{
'id' => se1.id,
'message' => 'sub 1',
'user_id' => @student.id,
'user_name' => 'User',
'created_at' => se1.created_at.as_json,
'updated_at' => se1.updated_at.as_json,
},
{
'id' => se2.id,
'message' => 'student 1',
'user_id' => @student.id,
'user_name' => 'User',
'created_at' => se2.created_at.as_json,
'updated_at' => se2.updated_at.as_json,
}].sort_by { |h| h['user_id'] }