importing more canvas export types
Added external feeds, grading standards, and learning outcomes refs #3396 Change-Id: I138f22a6d5793e21ba49388e16be75d5f80f0e12 Reviewed-on: https://gerrit.instructure.com/3043 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Brian Palmer <brianp@instructure.com>
This commit is contained in:
parent
bb8bc24cd7
commit
84c048e5e6
|
@ -1189,6 +1189,8 @@ class Course < ActiveRecord::Base
|
|||
Rubric.process_migration(data, migration)
|
||||
@assignment_group_no_drop_assignments = {}
|
||||
AssignmentGroup.process_migration(data, migration)
|
||||
ExternalFeed.process_migration(data, migration)
|
||||
GradingStandard.process_migration(data, migration)
|
||||
migration.fast_update_progress(40)
|
||||
Quiz.process_migration(data, migration, question_data)
|
||||
migration.fast_update_progress(50)
|
||||
|
|
|
@ -183,4 +183,32 @@ class ExternalFeed < ActiveRecord::Base
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
def self.process_migration(data, migration)
|
||||
tools = data['external_feeds'] ? data['external_feeds']: []
|
||||
to_import = migration.to_import 'external_feeds'
|
||||
tools.each do |tool|
|
||||
if tool['migration_id'] && (!to_import || to_import[tool['migration_id']])
|
||||
import_from_migration(tool, migration.context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:external_feeds_to_import] && !hash[:external_feeds_to_import][hash[:migration_id]]
|
||||
item ||= find_by_context_id_and_context_type_and_migration_id(context.id, context.class.to_s, hash[:migration_id]) if hash[:migration_id]
|
||||
item ||= context.external_feeds.new
|
||||
item.migration_id = hash[:migration_id]
|
||||
item.url = hash[:url]
|
||||
item.title = hash[:title]
|
||||
item.feed_type = hash[:feed_type]
|
||||
item.feed_purpose = hash[:purpose]
|
||||
item.verbosity = hash[:verbosity]
|
||||
item.header_match = hash[:header_match] unless hash[:header_match].blank?
|
||||
|
||||
item.save!
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
item
|
||||
end
|
||||
end
|
||||
|
|
|
@ -107,4 +107,33 @@ class GradingStandard < ActiveRecord::Base
|
|||
# "F" => 0.0
|
||||
# }
|
||||
end
|
||||
|
||||
def self.process_migration(data, migration)
|
||||
standards = data['grading_standards'] ? data['grading_standards']: []
|
||||
to_import = migration.to_import 'grading_standards'
|
||||
standards.each do |tool|
|
||||
if tool['migration_id'] && (!to_import || to_import[tool['migration_id']])
|
||||
import_from_migration(tool, migration.context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
return nil if hash[:migration_id] && hash[:grading_standards_to_import] && !hash[:grading_standards_to_import][hash[:migration_id]]
|
||||
item ||= find_by_context_id_and_context_type_and_migration_id(context.id, context.class.to_s, hash[:migration_id]) if hash[:migration_id]
|
||||
item ||= context.grading_standards.new
|
||||
item.migration_id = hash[:migration_id]
|
||||
item.title = hash[:title]
|
||||
begin
|
||||
item.data = JSON.parse hash[:data]
|
||||
rescue
|
||||
#todo - add to message to display to user
|
||||
end
|
||||
|
||||
item.save!
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
item
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -169,9 +169,10 @@ class LearningOutcome < ActiveRecord::Base
|
|||
|
||||
def self.process_migration(data, migration)
|
||||
outcomes = data['learning_outcomes'] ? data['learning_outcomes'] : []
|
||||
to_import = migration.to_import 'learning_outcomes'
|
||||
outcomes.each do |outcome|
|
||||
if !to_import || to_import[migration_id]
|
||||
if outcome[:type] == 'learning_outcome_group'
|
||||
LearningOutcomeGroup.import_from_migration(outcome, migration.context)
|
||||
else
|
||||
import_from_migration(outcome, migration.context)
|
||||
end
|
||||
end
|
||||
|
@ -183,12 +184,20 @@ class LearningOutcome < ActiveRecord::Base
|
|||
item ||= context.learning_outcomes.new
|
||||
item.context = context
|
||||
item.migration_id = hash[:migration_id]
|
||||
item.short_description = hash[:title]
|
||||
item.description = hash[:description]
|
||||
|
||||
|
||||
if hash[:ratings]
|
||||
item.data = {:rubric_criterion=>{:ratings=>hash[:ratings]}}
|
||||
item.data[:rubric_criterion][:mastery_points] = hash[:mastery_points]
|
||||
item.data[:rubric_criterion][:points_possible] = hash[:points_possible]
|
||||
item.data[:rubric_criterion][:description] = item.short_description || item.description
|
||||
end
|
||||
|
||||
item.save!
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
|
||||
log = LearningOutcomeGroup.default_for(context)
|
||||
|
||||
log = hash[:learning_outcome_group] || LearningOutcomeGroup.default_for(context)
|
||||
log.add_item(item)
|
||||
|
||||
item
|
||||
|
|
|
@ -155,6 +155,32 @@ class LearningOutcomeGroup < ActiveRecord::Base
|
|||
outcome
|
||||
end
|
||||
|
||||
def self.import_from_migration(hash, context, item=nil)
|
||||
hash = hash.with_indifferent_access
|
||||
item ||= find_by_context_id_and_context_type_and_migration_id(context.id, context.class.to_s, hash[:migration_id]) if hash[:migration_id]
|
||||
item ||= context.learning_outcome_groups.new
|
||||
item.context = context
|
||||
item.migration_id = hash[:migration_id]
|
||||
item.title = hash[:title]
|
||||
item.description = hash[:description]
|
||||
|
||||
item.save!
|
||||
|
||||
context.imported_migration_items << item if context.imported_migration_items && item.new_record?
|
||||
|
||||
if hash[:outcomes]
|
||||
hash[:outcomes].each do |outcome|
|
||||
outcome[:learning_outcome_group] = item
|
||||
LearningOutcome.import_from_migration(outcome, context)
|
||||
end
|
||||
end
|
||||
|
||||
log = LearningOutcomeGroup.default_for(context)
|
||||
log.add_item(item)
|
||||
|
||||
item
|
||||
end
|
||||
|
||||
named_scope :active, lambda{
|
||||
{:conditions => ['learning_outcome_groups.workflow_state != ?', 'deleted'] }
|
||||
}
|
||||
|
|
|
@ -17,11 +17,17 @@
|
|||
#
|
||||
module CC
|
||||
module ExternalFeeds
|
||||
def create_external_feeds
|
||||
def create_external_feeds(document=nil)
|
||||
return nil unless @course.external_feeds.count > 0
|
||||
feed_file = File.new(File.join(@canvas_resource_dir, CCHelper::EXTERNAL_FEEDS), 'w')
|
||||
rel_path = File.join(CCHelper::COURSE_SETTINGS_DIR, CCHelper::EXTERNAL_FEEDS)
|
||||
document = Builder::XmlMarkup.new(:target=>feed_file, :indent=>2)
|
||||
if document
|
||||
feed_file = nil
|
||||
rel_path = nil
|
||||
else
|
||||
feed_file = File.new(File.join(@canvas_resource_dir, CCHelper::EXTERNAL_FEEDS), 'w')
|
||||
rel_path = File.join(CCHelper::COURSE_SETTINGS_DIR, CCHelper::EXTERNAL_FEEDS)
|
||||
document = Builder::XmlMarkup.new(:target=>feed_file, :indent=>2)
|
||||
end
|
||||
|
||||
document.instruct!
|
||||
document.externalFeeds(
|
||||
"xmlns" => CCHelper::CANVAS_NAMESPACE,
|
||||
|
@ -41,7 +47,7 @@ module CC
|
|||
end
|
||||
end
|
||||
|
||||
feed_file.close
|
||||
feed_file.close if feed_file
|
||||
rel_path
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,12 +17,18 @@
|
|||
#
|
||||
module CC
|
||||
module GradingStandards
|
||||
def create_grading_standards
|
||||
def create_grading_standards(document=nil)
|
||||
return nil unless @course.grading_standards.count > 0
|
||||
|
||||
standards_file = File.new(File.join(@canvas_resource_dir, CCHelper::GRADING_STANDARDS), 'w')
|
||||
rel_path = File.join(CCHelper::COURSE_SETTINGS_DIR, CCHelper::GRADING_STANDARDS)
|
||||
document = Builder::XmlMarkup.new(:target=>standards_file, :indent=>2)
|
||||
if document
|
||||
standards_file = nil
|
||||
rel_path = nil
|
||||
else
|
||||
standards_file = File.new(File.join(@canvas_resource_dir, CCHelper::GRADING_STANDARDS), 'w')
|
||||
rel_path = File.join(CCHelper::COURSE_SETTINGS_DIR, CCHelper::GRADING_STANDARDS)
|
||||
document = Builder::XmlMarkup.new(:target=>standards_file, :indent=>2)
|
||||
end
|
||||
|
||||
document.instruct!
|
||||
document.gradingStandards(
|
||||
"xmlns" => CCHelper::CANVAS_NAMESPACE,
|
||||
|
@ -38,7 +44,7 @@ module CC
|
|||
end
|
||||
end
|
||||
|
||||
standards_file.close
|
||||
standards_file.close if standards_file
|
||||
rel_path
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,5 +23,6 @@ module CC
|
|||
end
|
||||
end
|
||||
|
||||
require 'cc/importer/learning_outcomes_converter'
|
||||
require 'cc/importer/course_settings'
|
||||
require 'cc/importer/cc_converter'
|
||||
|
|
|
@ -18,15 +18,19 @@
|
|||
module CC::Importer
|
||||
module CourseSettings
|
||||
include CC::Importer
|
||||
include LearningOutcomesConverter
|
||||
|
||||
def course_settings_doc(file)
|
||||
def settings_doc(file)
|
||||
open_file_xml File.join(@unzipped_file_path, COURSE_SETTINGS_DIR, file)
|
||||
end
|
||||
|
||||
def convert_non_dependant_course_settings
|
||||
@course[:course] = convert_course_settings(course_settings_doc(COURSE_SETTINGS))
|
||||
@course[:assignment_groups] = convert_assignment_groups(course_settings_doc(ASSIGNMENT_GROUPS))
|
||||
@course[:external_tools] = convert_external_tools(course_settings_doc(EXTERNAL_TOOLS))
|
||||
@course[:course] = convert_course_settings(settings_doc(COURSE_SETTINGS))
|
||||
@course[:assignment_groups] = convert_assignment_groups(settings_doc(ASSIGNMENT_GROUPS))
|
||||
@course[:external_tools] = convert_external_tools(settings_doc(EXTERNAL_TOOLS))
|
||||
@course[:external_feeds] = convert_external_feeds(settings_doc(EXTERNAL_FEEDS))
|
||||
@course[:grading_standards] = convert_grading_standards(settings_doc(GRADING_STANDARDS))
|
||||
@course[:learning_outcomes] = convert_learning_outcomes(settings_doc(LEARNING_OUTCOMES))
|
||||
end
|
||||
|
||||
def convert_course_settings(doc)
|
||||
|
@ -100,5 +104,38 @@ module CC::Importer
|
|||
tools
|
||||
end
|
||||
|
||||
def convert_external_feeds(doc)
|
||||
feeds = []
|
||||
return feeds unless doc
|
||||
doc.css('externalFeed').each do |node|
|
||||
feed = {}
|
||||
feed['migration_id'] = node['identifier']
|
||||
feed['title'] = get_node_val(node, 'title')
|
||||
feed['url'] = get_node_val(node, 'url')
|
||||
feed['feed_type'] = get_node_val(node, 'feed_type')
|
||||
feed['purpose'] = get_node_val(node, 'purpose')
|
||||
feed['verbosity'] = get_node_val(node, 'verbosity')
|
||||
feed['header_match'] = get_node_val(node, 'header_match')
|
||||
|
||||
feeds << feed
|
||||
end
|
||||
|
||||
feeds
|
||||
end
|
||||
|
||||
def convert_grading_standards(doc)
|
||||
standards = []
|
||||
return standards unless doc
|
||||
doc.css('gradingStandard').each do |node|
|
||||
standard = {}
|
||||
standard['migration_id'] = node['identifier']
|
||||
standard['title'] = get_node_val(node, 'title')
|
||||
standard['data'] = get_node_val(node, 'data')
|
||||
standards << standard
|
||||
end
|
||||
|
||||
standards
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,83 @@
|
|||
#
|
||||
# Copyright (C) 2011 Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
module CC::Importer
|
||||
module LearningOutcomesConverter
|
||||
include CC::Importer
|
||||
|
||||
def convert_learning_outcomes(doc)
|
||||
outcomes = []
|
||||
return outcomes unless doc
|
||||
|
||||
doc.at_css('learningOutcomes').children.each do |child|
|
||||
if child.name == 'learningOutcome'
|
||||
outcomes << process_learning_outcome(child)
|
||||
elsif child.name == 'learningOutcomeGroup'
|
||||
outcomes << process_outcome_group(child)
|
||||
end
|
||||
end
|
||||
|
||||
outcomes
|
||||
end
|
||||
|
||||
def process_outcome_group(node)
|
||||
group = {}
|
||||
group[:migration_id] = node['identifier']
|
||||
group[:title] = get_val_if_child(node, 'title')
|
||||
group[:type] = 'learning_outcome_group'
|
||||
group[:description] = get_val_if_child(node, 'description')
|
||||
group[:outcomes] = []
|
||||
|
||||
node.css('learningOutcome').each do |out_node|
|
||||
group[:outcomes] << process_learning_outcome(out_node)
|
||||
end
|
||||
|
||||
group
|
||||
end
|
||||
|
||||
def process_learning_outcome(node)
|
||||
outcome = {}
|
||||
outcome[:migration_id] = node['identifier']
|
||||
outcome[:title] = get_node_val(node, 'title')
|
||||
outcome[:type] = 'learning_outcome'
|
||||
outcome[:description] = get_val_if_child(node, 'description')
|
||||
outcome[:mastery_points] = get_float_val(node, 'mastery_points')
|
||||
outcome[:points_possible] = get_float_val(node, 'points_possible')
|
||||
outcome[:ratings] = []
|
||||
|
||||
node.css('rating').each do |r_node|
|
||||
rating = {}
|
||||
rating[:description] = get_node_val(r_node, 'description')
|
||||
rating[:points] = get_float_val(r_node, 'points')
|
||||
outcome[:ratings] << rating
|
||||
end
|
||||
|
||||
outcome
|
||||
end
|
||||
|
||||
# You can't do a css selector that only looks for direct
|
||||
# descendants of the current node, so you have to iterate
|
||||
# over the children and see if it's there.
|
||||
def get_val_if_child(node, name)
|
||||
if child = node.children.find{|c|c.name == name}
|
||||
return child.text
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -17,15 +17,21 @@
|
|||
#
|
||||
module CC
|
||||
module LearningOutcomes
|
||||
def create_learning_outcomes
|
||||
def create_learning_outcomes(document=nil)
|
||||
return nil unless LearningOutcome.active.find_all_by_context_id_and_context_type(@course.id, 'Course').count > 0
|
||||
return nil unless @course.learning_outcome_groups.find_by_learning_outcome_group_id(nil)
|
||||
|
||||
root_group = @course.learning_outcome_groups.find_by_learning_outcome_group_id(nil)
|
||||
|
||||
if document
|
||||
outcomes_file = nil
|
||||
rel_path = nil
|
||||
else
|
||||
outcomes_file = File.new(File.join(@canvas_resource_dir, CCHelper::LEARNING_OUTCOMES), 'w')
|
||||
rel_path = File.join(CCHelper::COURSE_SETTINGS_DIR, CCHelper::LEARNING_OUTCOMES)
|
||||
document = Builder::XmlMarkup.new(:target=>outcomes_file, :indent=>2)
|
||||
end
|
||||
|
||||
outcomes_file = File.new(File.join(@canvas_resource_dir, CCHelper::LEARNING_OUTCOMES), 'w')
|
||||
rel_path = File.join(CCHelper::COURSE_SETTINGS_DIR, CCHelper::LEARNING_OUTCOMES)
|
||||
document = Builder::XmlMarkup.new(:target=>outcomes_file, :indent=>2)
|
||||
document.instruct!
|
||||
document.learningOutcomes(
|
||||
"xmlns" => CCHelper::CANVAS_NAMESPACE,
|
||||
|
@ -35,7 +41,7 @@ module CC
|
|||
process_outcome_group_content(outs_node, root_group)
|
||||
end
|
||||
|
||||
outcomes_file.close
|
||||
outcomes_file.close if outcomes_file
|
||||
rel_path
|
||||
end
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ describe "Common Cartridge importing" do
|
|||
end
|
||||
end
|
||||
|
||||
it "should convert assignment groups" do
|
||||
it "should import assignment groups" do
|
||||
ag1 = @copy_from.assignment_groups.new
|
||||
ag1.name = "Boring assignments"
|
||||
ag1.position = 1
|
||||
|
@ -116,7 +116,7 @@ describe "Common Cartridge importing" do
|
|||
ag2_2.rules.should == "drop_lowest:2\ndrop_highest:5\nnever_drop:%s\n" % a_2.id
|
||||
end
|
||||
|
||||
it "should convert external tools" do
|
||||
it "should import external tools" do
|
||||
tool1 = @copy_from.context_external_tools.new
|
||||
tool1.url = 'http://instructure.com'
|
||||
tool1.name = 'instructure'
|
||||
|
@ -163,5 +163,109 @@ describe "Common Cartridge importing" do
|
|||
t2.consumer_key.should == 'fake'
|
||||
t2.shared_secret.should == 'fake'
|
||||
end
|
||||
|
||||
it "should import external feeds" do
|
||||
ef = @copy_from.external_feeds.new
|
||||
ef.url = "http://search.twitter.com/search.atom?q=instructure"
|
||||
ef.title = "Instructure on Twitter"
|
||||
ef.feed_type = "rss/atom"
|
||||
ef.feed_purpose = 'announcements'
|
||||
ef.verbosity = 'full'
|
||||
ef.header_match = "canvas"
|
||||
ef.save!
|
||||
|
||||
#export to xml
|
||||
builder = Builder::XmlMarkup.new(:indent=>2)
|
||||
@resource.create_external_feeds(builder)
|
||||
#convert to json
|
||||
doc = Nokogiri::XML(builder.target!)
|
||||
hash = @converter.convert_external_feeds(doc)
|
||||
#import json into new course
|
||||
ExternalFeed.process_migration({'external_feeds'=>hash}, @migration)
|
||||
@copy_to.save!
|
||||
|
||||
ef_2 = @copy_to.external_feeds.find_by_migration_id(CC::CCHelper.create_key(ef))
|
||||
ef_2.url.should == ef.url
|
||||
ef_2.title.should == ef.title
|
||||
ef_2.feed_type.should == ef.feed_type
|
||||
ef_2.feed_purpose.should == ef.feed_purpose
|
||||
ef_2.verbosity.should == ef.verbosity
|
||||
ef_2.header_match.should == ef.header_match
|
||||
end
|
||||
|
||||
it "should import grading standards" do
|
||||
gs = @copy_from.grading_standards.new
|
||||
gs.title = "Standard eh"
|
||||
gs.data = [["A", 1], ["A-", 0.92], ["B+", 0.88], ["B", 0.84], ["B!-", 0.82], ["C+", 0.79], ["C", 0.76], ["C-", 0.73], ["D+", 0.69], ["D", 0.66], ["D-", 0.63], ["F", 0.6]]
|
||||
gs.save!
|
||||
|
||||
#export to xml
|
||||
builder = Builder::XmlMarkup.new(:indent=>2)
|
||||
@resource.create_grading_standards(builder)
|
||||
#convert to json
|
||||
doc = Nokogiri::XML(builder.target!)
|
||||
hash = @converter.convert_grading_standards(doc)
|
||||
#import json into new course
|
||||
GradingStandard.process_migration({'grading_standards'=>hash}, @migration)
|
||||
@copy_to.save!
|
||||
|
||||
gs_2 = @copy_to.grading_standards.find_by_migration_id(CC::CCHelper.create_key(gs))
|
||||
gs_2.title.should == gs.title
|
||||
gs_2.data.should == gs.data
|
||||
end
|
||||
|
||||
it "should import learning outcomes" do
|
||||
lo = @copy_from.learning_outcomes.new
|
||||
lo.context = @copy_from
|
||||
lo.short_description = "Lone outcome"
|
||||
lo.description = "<p>Descriptions are boring</p>"
|
||||
lo.workflow_state = 'active'
|
||||
lo.data = {:rubric_criterion=>{:mastery_points=>3, :ratings=>[{:description=>"Exceeds Expectations", :points=>5}, {:description=>"Meets Expectations", :points=>3}, {:description=>"Does Not Meet Expectations", :points=>0}], :description=>"First outcome", :points_possible=>5}}
|
||||
lo.save!
|
||||
|
||||
default = LearningOutcomeGroup.default_for(@copy_from)
|
||||
default.add_item(lo)
|
||||
|
||||
lo_g = @copy_from.learning_outcome_groups.new
|
||||
lo_g.context = @copy_from
|
||||
lo_g.title = "Lone outcome group"
|
||||
lo_g.description = "<p>Groupage</p>"
|
||||
lo_g.save!
|
||||
|
||||
lo2 = @copy_from.learning_outcomes.new
|
||||
lo2.context = @copy_from
|
||||
lo2.short_description = "outcome in group"
|
||||
lo2.workflow_state = 'active'
|
||||
lo2.data = {:rubric_criterion=>{:mastery_points=>2, :ratings=>[{:description=>"e", :points=>50}, {:description=>"me", :points=>2}, {:description=>"Does Not Meet Expectations", :points=>0.5}], :description=>"First outcome", :points_possible=>5}}
|
||||
lo2.save!
|
||||
lo_g.add_item(lo2)
|
||||
|
||||
default.add_item(lo_g)
|
||||
|
||||
#export to xml
|
||||
builder = Builder::XmlMarkup.new(:indent=>2)
|
||||
@resource.create_learning_outcomes(builder)
|
||||
#convert to json
|
||||
doc = Nokogiri::XML(builder.target!)
|
||||
hash = @converter.convert_learning_outcomes(doc)
|
||||
#import json into new course
|
||||
LearningOutcome.process_migration({'learning_outcomes'=>hash}, @migration)
|
||||
@copy_to.save!
|
||||
|
||||
lo_2 = @copy_to.learning_outcomes.find_by_migration_id(CC::CCHelper.create_key(lo))
|
||||
lo_2.short_description.should == lo.short_description
|
||||
lo_2.description.should == lo.description
|
||||
lo_2.data.with_indifferent_access.should == lo.data.with_indifferent_access
|
||||
|
||||
lo2_2 = @copy_to.learning_outcomes.find_by_migration_id(CC::CCHelper.create_key(lo2))
|
||||
lo2_2.short_description.should == lo2.short_description
|
||||
lo2_2.description.should == lo2.description
|
||||
lo2_2.data.with_indifferent_access.should == lo2.data.with_indifferent_access
|
||||
|
||||
lo_g_2 = @copy_to.learning_outcome_groups.find_by_migration_id(CC::CCHelper.create_key(lo_g))
|
||||
lo_g_2.title.should == lo_g.title
|
||||
lo_g_2.description.should == lo_g.description
|
||||
lo_g_2.sorted_content.length.should == 1
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue