return discussion_type in topics api response

We changed the threaded boolean to a discussion_type string, with
currently two types: 'side_comment' and 'threaded'

test plan: get the list of topics in the api, verify threaded is
returned appropriately.

Change-Id: Id5bfb867329d93fe8be6131e2e7c401f70ced290
Reviewed-on: https://gerrit.instructure.com/9647
Reviewed-by: Zach Wily <zach@instructure.com>
Tested-by: Hudson <hudson@instructure.com>
This commit is contained in:
Brian Palmer 2012-03-27 19:10:47 -06:00
parent b8262b0cb7
commit 409f78de9a
9 changed files with 63 additions and 7 deletions

View File

@ -48,6 +48,7 @@ class DiscussionTopicsController < ApplicationController
# @response_field topic_children An array of topic_ids for the group discussions the user is a part of # @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 user_name The username of the creator
# @response_field url The URL to the discussion topic in canvas # @response_field url The URL to the discussion topic in canvas
# @response_field discussion_type The type of discussion. Values are 'side_comment', for discussions that only allow one level of nested comments, and 'threaded' for fully threaded discussions.
# @response_field permissions[attach] If true, the calling user can attach files to this discussion's entries. # @response_field permissions[attach] If true, the calling user can attach files to this discussion's entries.
# #
# @example_response # @example_response
@ -68,6 +69,7 @@ class DiscussionTopicsController < ApplicationController
# "topic_children":[], # "topic_children":[],
# "root_topic_id":null, # "root_topic_id":null,
# "podcast_url":"/feeds/topics/1/enrollment_1XAcepje4u228rt4mi7Z1oFbRpn3RAkTzuXIGOPe.rss", # "podcast_url":"/feeds/topics/1/enrollment_1XAcepje4u228rt4mi7Z1oFbRpn3RAkTzuXIGOPe.rss",
# "discussion_type":"side_comment",
# "attachments":[ # "attachments":[
# { # {
# "content-type":"unknown/unknown", # "content-type":"unknown/unknown",

View File

@ -26,7 +26,13 @@ class DiscussionTopic < ActiveRecord::Base
attr_accessible :title, :message, :user, :delayed_post_at, :assignment, attr_accessible :title, :message, :user, :delayed_post_at, :assignment,
:plaintext_message, :podcast_enabled, :podcast_has_student_posts, :plaintext_message, :podcast_enabled, :podcast_has_student_posts,
:require_initial_post, :threaded :require_initial_post, :threaded, :discussion_type
module DiscussionTypes
SIDE_COMMENT = 'side_comment'
THREADED = 'threaded'
TYPES = DiscussionTypes.constants.map { |c| DiscussionTypes.const_get(c) }
end
attr_readonly :context_id, :context_type, :user_id attr_readonly :context_id, :context_type, :user_id
@ -48,6 +54,7 @@ class DiscussionTopic < ActiveRecord::Base
belongs_to :user belongs_to :user
validates_presence_of :context_id validates_presence_of :context_id
validates_presence_of :context_type validates_presence_of :context_type
validates_presence_of :discussion_type, :in => DiscussionTypes::TYPES
validates_length_of :message, :maximum => maximum_long_text_length, :allow_nil => true, :allow_blank => true validates_length_of :message, :maximum => maximum_long_text_length, :allow_nil => true, :allow_blank => true
validates_length_of :title, :maximum => maximum_string_length, :allow_nil => true validates_length_of :title, :maximum => maximum_string_length, :allow_nil => true
@ -65,9 +72,22 @@ class DiscussionTopic < ActiveRecord::Base
after_create :create_participant after_create :create_participant
after_create :create_materialized_view after_create :create_materialized_view
def threaded=(v)
self.discussion_type = Canvas::Plugin.value_to_boolean(v) ? DiscussionTypes::THREADED : DiscussionTypes::SIDE_COMMENT
end
def threaded?
self.discussion_type == DiscussionTypes::THREADED
end
def discussion_type
read_attribute(:discussion_type) || DiscussionTypes::SIDE_COMMENT
end
def default_values def default_values
self.context_code = "#{self.context_type.underscore}_#{self.context_id}" self.context_code = "#{self.context_type.underscore}_#{self.context_id}"
self.title ||= t '#discussion_topic.default_title', "No Title" self.title ||= t '#discussion_topic.default_title', "No Title"
self.discussion_type = DiscussionTypes::SIDE_COMMENT if !read_attribute(:discussion_type)
@content_changed = self.message_changed? || self.title_changed? @content_changed = self.message_changed? || self.title_changed?
if self.assignment_id != self.assignment_id_was if self.assignment_id != self.assignment_id_was
@old_assignment_id = self.assignment_id_was @old_assignment_id = self.assignment_id_was
@ -106,7 +126,7 @@ class DiscussionTopic < ActiveRecord::Base
topic.title = "#{self.title} - #{group.name}" topic.title = "#{self.title} - #{group.name}"
topic.assignment_id = self.assignment_id topic.assignment_id = self.assignment_id
topic.user_id = self.user_id topic.user_id = self.user_id
topic.threaded = self.threaded topic.discussion_type = self.discussion_type
topic.save if topic.changed? topic.save if topic.changed?
topic topic
end end

View File

@ -119,7 +119,7 @@
<span class="podcast_enabled"><%= (topic && topic.podcast_enabled) ? "1" : "0" %></span> <span class="podcast_enabled"><%= (topic && topic.podcast_enabled) ? "1" : "0" %></span>
<span class="podcast_has_student_posts"><%= (topic && topic.podcast_has_student_posts) ? "1" : "0" %></span> <span class="podcast_has_student_posts"><%= (topic && topic.podcast_has_student_posts) ? "1" : "0" %></span>
<span class="require_initial_post"><%= (topic && topic.require_initial_post) ? "1" : "0" %></span> <span class="require_initial_post"><%= (topic && topic.require_initial_post) ? "1" : "0" %></span>
<span class="threaded"><%= (topic && topic.threaded) ? "1" : "0" %></span> <span class="threaded"><%= topic.try(:threaded?) ? "1" : "0" %></span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,13 @@
class AddDiscussionTopicType < ActiveRecord::Migration
tag :predeploy
def self.up
remove_column :discussion_topics, :threaded
add_column :discussion_topics, :discussion_type, :string
end
def self.down
remove_column :discussion_topics, :discussion_type
add_column :discussion_topics, :threaded, :boolean
end
end

View File

@ -45,6 +45,7 @@ module Api::V1::DiscussionTopics
:methods => [:user_name, :discussion_subentry_count], }, [:attach] :methods => [:user_name, :discussion_subentry_count], }, [:attach]
).tap do |json| ).tap do |json|
json.merge! :message => api_user_content(topic.message, context), json.merge! :message => api_user_content(topic.message, context),
:discussion_type => topic.discussion_type,
:podcast_url => url, :podcast_url => url,
:read_state => topic.read_state(user), :read_state => topic.read_state(user),
:unread_count => topic.unread_count(user), :unread_count => topic.unread_count(user),

View File

@ -243,6 +243,7 @@ describe AssignmentsApiController, :type => :integration do
'url' => "http://www.example.com/courses/#{@course.id}/discussion_topics/#{@topic.id}", 'url' => "http://www.example.com/courses/#{@course.id}/discussion_topics/#{@topic.id}",
'attachments' => [], 'attachments' => [],
'permissions' => { 'attach' => true }, 'permissions' => { 'attach' => true },
'discussion_type' => 'side_comment',
} }
end end

View File

@ -95,6 +95,7 @@ describe DiscussionTopicsController, :type => :integration do
"size"=>attachment.size, "size"=>attachment.size,
}], }],
"topic_children"=>[sub.id], "topic_children"=>[sub.id],
"discussion_type" => 'side_comment',
"permissions" => { "attach" => true }} "permissions" => { "attach" => true }}
end end
@ -165,6 +166,7 @@ describe DiscussionTopicsController, :type => :integration do
"posted_at"=>gtopic.posted_at.as_json, "posted_at"=>gtopic.posted_at.as_json,
"root_topic_id"=>nil, "root_topic_id"=>nil,
"topic_children"=>[], "topic_children"=>[],
"discussion_type" => 'side_comment',
"permissions" => { "attach" => true }} "permissions" => { "attach" => true }}
end end
@ -826,6 +828,12 @@ describe DiscussionTopicsController, :type => :integration do
end end
context "in the original API" do context "in the original API" do
it "should respond with information on the threaded discussion" do
json = api_call(:get, "/api/v1/courses/#{@course.id}/discussion_topics",
{ :controller => "discussion_topics", :action => "index", :format => "json", :course_id => @course.id.to_s })
json[0]['discussion_type'].should == 'threaded'
end
it "should return nested discussions in a flattened format" do it "should return nested discussions in a flattened format" do
json = api_call(:get, "/api/v1/courses/#{@course.id}/discussion_topics/#{@topic.id}/entries", json = api_call(:get, "/api/v1/courses/#{@course.id}/discussion_topics/#{@topic.id}/entries",
{ :controller => "discussion_topics_api", :action => "entries", :format => "json", :course_id => @course.id.to_s, :topic_id => @topic.id.to_s }) { :controller => "discussion_topics_api", :action => "entries", :format => "json", :course_id => @course.id.to_s, :topic_id => @topic.id.to_s })

View File

@ -40,7 +40,7 @@ end
def topic_with_nested_replies(opts = {}) def topic_with_nested_replies(opts = {})
course_with_teacher(:active_all => true) course_with_teacher(:active_all => true)
student_in_course(:course => @course, :active_all => true) student_in_course(:course => @course, :active_all => true)
@topic = @course.discussion_topics.create!(:title => "title", :message => "message", :user => @teacher, :threaded => true) @topic = @course.discussion_topics.create!(:title => "title", :message => "message", :user => @teacher, :discussion_type => 'threaded')
@root1 = @topic.reply_from(:user => @student, :html => "root1") @root1 = @topic.reply_from(:user => @student, :html => "root1")
@root2 = @topic.reply_from(:user => @student, :html => "root2") @root2 = @topic.reply_from(:user => @student, :html => "root2")
@reply1 = @root1.reply_from(:user => @teacher, :html => "reply1") @reply1 = @root1.reply_from(:user => @teacher, :html => "reply1")

View File

@ -25,6 +25,17 @@ describe DiscussionTopic do
@course.discussion_topics.first.message.should eql("<a href=\"#\">only this should stay</a>") @course.discussion_topics.first.message.should eql("<a href=\"#\">only this should stay</a>")
end end
it "should default to side_comment type" do
d = DiscussionTopic.new
d.discussion_type.should == 'side_comment'
d.threaded = '1'
d.discussion_type.should == 'threaded'
d.threaded = ''
d.discussion_type.should == 'side_comment'
end
it "should update the assignment it is associated with" do it "should update the assignment it is associated with" do
course_model course_model
a = @course.assignments.create!(:title => "some assignment", :points_possible => 5) a = @course.assignments.create!(:title => "some assignment", :points_possible => 5)
@ -248,10 +259,10 @@ describe DiscussionTopic do
it "should copy appropriate attributes from the parent topic to subtopics on updates to the parent" do it "should copy appropriate attributes from the parent topic to subtopics on updates to the parent" do
topic_for_group_assignment topic_for_group_assignment
subtopics = @topic.refresh_subtopics subtopics = @topic.refresh_subtopics
subtopics.each {|st| st.threaded.should be_nil } subtopics.each {|st| st.discussion_type.should == 'side_comment' }
@topic.threaded = true @topic.discussion_type = 'threaded'
@topic.save @topic.save
subtopics.each {|st| st.reload.threaded.should == true } subtopics.each {|st| st.reload.discussion_type.should == 'threaded' }
end end
end end