Commit ebbbbe6d by Xavier Antoviaque

student-results-migration: Migrate data stored in the `student_results` field

Format change broke backward-compatibility with the previous data format.
Changed `completed` to `status` in `self.student_results` to accomodate
partial responses.
parent eb5de98f
......@@ -39,7 +39,6 @@ from xblock.fragment import Fragment
from .light_children import XBlockWithLightChildren
from .title import TitleBlock
from .header import SharedHeaderBlock
from .html import HTMLBlock
from .message import MentoringMessageBlock
from .step import StepParentMixin
from .utils import loader
......@@ -142,6 +141,9 @@ class MentoringBlock(XBlockWithLightChildren, StepParentMixin):
return Score(score, int(round(score * 100)), correct, incorrect, partially_correct)
def student_view(self, context):
# Migrate stored data if necessary
self.migrate_fields()
fragment, named_children = self.get_children_fragment(
context, view_name='mentoring_view',
not_instance_of=self.FLOATING_BLOCKS,
......@@ -172,6 +174,18 @@ class MentoringBlock(XBlockWithLightChildren, StepParentMixin):
return fragment
def migrate_fields(self):
"""
Migrate data stored in the fields, when a format change breaks backward-compatibility with
previous data formats
"""
# Partial answers replaced the `completed` with `status` in `self.student_results`
if self.student_results and 'completed' in self.student_results[0][1]:
# Rename the field and use the new value format (text instead of boolean)
for result in self.student_results:
result[1]['status'] = 'correct' if result[1]['completed'] else 'incorrect'
del result[1]['completed']
@property
def additional_publish_event_data(self):
return {
......
import copy
import unittest
from mock import MagicMock, Mock
from lxml import etree
from xblock.field_data import DictFieldData
from mentoring import MentoringBlock
import mentoring
from mentoring.step import StepMixin, StepParentMixin
......@@ -78,3 +79,37 @@ class TestStepMixin(unittest.TestCase):
self.assertFalse(step1.lonely_step)
self.assertFalse(step2.lonely_step)
class TestFieldMigration(unittest.TestCase):
"""
Test mentoring fields data migration
"""
def test_partial_completion_status_migration(self):
"""
Changed `completed` to `status` in `self.student_results` to accomodate partial responses
"""
# Instantiate a mentoring block with the old format
student_results = [
[ u'goal',
{ u'completed': True,
u'score': 1,
u'student_input': u'test',
u'weight': 1}],
[ u'mcq_1_1',
{ u'completed': False,
u'score': 0,
u'submission': u'maybenot',
u'weight': 1}],
]
mentoring = MentoringBlock(MagicMock(), DictFieldData({'student_results': student_results}), Mock())
self.assertEqual(copy.deepcopy(student_results), mentoring.student_results)
migrated_student_results = copy.deepcopy(student_results)
migrated_student_results[0][1]['status'] = 'correct'
migrated_student_results[1][1]['status'] = 'incorrect'
del migrated_student_results[0][1]['completed']
del migrated_student_results[1][1]['completed']
mentoring.migrate_fields()
self.assertEqual(migrated_student_results, mentoring.student_results)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment