Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scale rubric criterion levels on max_mark update #7311

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### 🐛 Bug fixes

- Ensures row selection for peer reviewer unassigning has the same validation checks as individual selections (#7274)
- Ensures mark levels on a rubric criterion are properly scaled when its max mark is updated (#7311)
- Refactor contributors list in About section to read from markus-contributors.txt (#7374)

### 🔧 Internal changes
Expand Down
6 changes: 1 addition & 5 deletions app/controllers/criteria_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,7 @@ def update
end
if @criterion.is_a? RubricCriterion
# update everything except levels and assignments
properly_updated = @criterion.update(rubric_criterion_params.except(:levels_attributes, :assignment_files))
# update levels
if rubric_criterion_params[:levels_attributes]
properly_updated &&= @criterion.update_levels(rubric_criterion_params[:levels_attributes])
end
properly_updated = @criterion.update(rubric_criterion_params.except(:assignment_files))
unless rubric_criterion_params[:assignment_files].nil?
assignment_files = AssignmentFile.find(rubric_criterion_params[:assignment_files].reject(&:empty?))
end
Expand Down
23 changes: 0 additions & 23 deletions app/models/rubric_criterion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,6 @@ class RubricCriterion < Criterion
validates :levels, presence: true

DEFAULT_MAX_MARK = 4
# Checks whether the passed in param's level_attributes have unique name and marks.
# Skips the uniqueness validation if true.
def update_levels(levels_attributes)
s1, s2 = Set[], Set[]
should_skip = true

# Check if there's a dup in marks or names
levels_attributes.each_value do |val|
if s1.include?(val[:mark]) || s2.include?(val[:name])
should_skip = false
break
end
s1.add(val[:mark])
s2.add(val[:name])
end

if should_skip
levels_attributes.each_value do |val|
val[:skip_uniqueness_validation] = true
end
end
self.update(levels_attributes: levels_attributes)
end

def level_with_mark_closest_to(mark)
self.levels.min_by { |m| (m.mark - mark).abs }
Expand Down
114 changes: 0 additions & 114 deletions spec/models/rubric_criterion_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,120 +5,6 @@
it_behaves_like 'a criterion'
end

describe '#update_levels' do
# At creation, rubric already has 5 levels
let(:rubric) { create(:rubric_criterion) }

context 'when the properties with uniqueness validations are changed in a way
that two properties A and B have switched values' do
context 'when the names are changed and the marks are not changed' do
it 'updates the associated levels if all the levels after update will have unique names' do
level0_mark, level0_name, level0_id = rubric.levels[0].mark, rubric.levels[0].name, rubric.levels[0].id
level1_mark, level1_name, level1_id = rubric.levels[1].mark, rubric.levels[1].name, rubric.levels[1].id

params = {
'0' => { mark: level0_mark, name: level1_name, id: level0_id },
'1' => { mark: level1_mark, name: level0_name, id: level1_id }
}
rubric.update_levels(params)

expect(rubric.levels.find_by(id: level0_id).name).to eq(level1_name)
expect(rubric.levels.find_by(id: level1_id).name).to eq(level0_name)
end
end

context 'when the marks are changed and the names are not changed' do
it 'updates the associated levels if all the levels after update will have unique marks' do
level0_mark, level0_name, level0_id = rubric.levels[0].mark, rubric.levels[0].name, rubric.levels[0].id
level1_mark, level1_name, level1_id = rubric.levels[1].mark, rubric.levels[1].name, rubric.levels[1].id

params = {
'0' => { mark: level1_mark, name: level0_name, id: level0_id },
'1' => { mark: level0_mark, name: level1_name, id: level1_id }
}
rubric.update_levels(params)

expect(rubric.levels.find_by(id: level0_id).mark).to eq(level1_mark)
expect(rubric.levels.find_by(id: level1_id).mark).to eq(level0_mark)
end
end

context 'when both the marks and the names are changed' do
it 'updates the associated levels if all the levels after update will have unique marks' do
level0_mark, level0_name, level0_id = rubric.levels[0].mark, rubric.levels[0].name, rubric.levels[0].id
level1_mark, level1_name, level1_id = rubric.levels[1].mark, rubric.levels[1].name, rubric.levels[1].id

params = {
'0' => { mark: level1_mark, name: level1_name, id: level0_id },
'1' => { mark: level0_mark, name: level0_name, id: level1_id }
}
rubric.update_levels(params)

expect(rubric.levels.find_by(id: level0_id).mark).to eq(level1_mark)
expect(rubric.levels.find_by(id: level1_id).mark).to eq(level0_mark)
expect(rubric.levels.find_by(id: level0_id).name).to eq(level1_name)
expect(rubric.levels.find_by(id: level1_id).name).to eq(level0_name)
end
end
end

context 'when the properties with uniqueness validations are changed in a way that the validation is be violated' do
context 'when the names are changed and the marks are not changed' do
it 'does not update associated levels' do
level0_mark, level0_id = rubric.levels[0].mark, rubric.levels[0].id
level1_mark, level1_name, level1_id = rubric.levels[1].mark, rubric.levels[1].name, rubric.levels[1].id

params = {
'0' => { name: level1_name, mark: level0_mark, id: level0_id },
'1' => { name: level1_name, mark: level1_mark, id: level1_id }
}
level0_before = rubric.levels.find_by(id: level0_id)
level1_before = rubric.levels.find_by(id: level1_id)
rubric.update_levels(params)

expect(rubric.levels.find_by(id: level0_id)).to eq(level0_before)
expect(rubric.levels.find_by(id: level1_id)).to eq(level1_before)
end
end

context 'when the marks are changed and the names are not changed' do
it 'does not update associated levels' do
level0_name, level0_id = rubric.levels[0].name, rubric.levels[0].id
level1_mark, level1_name, level1_id = rubric.levels[1].mark, rubric.levels[1].name, rubric.levels[1].id

params = {
'0' => { name: level0_name, mark: level1_mark, id: level0_id },
'1' => { name: level1_name, mark: level1_mark, id: level1_id }
}
level0_before = rubric.levels.find_by(id: level0_id)
level1_before = rubric.levels.find_by(id: level1_id)
rubric.update_levels(params)

expect(rubric.levels.find_by(id: level0_id)).to eq(level0_before)
expect(rubric.levels.find_by(id: level1_id)).to eq(level1_before)
end
end

context 'when both the marks and the names are changed' do
it 'does not update associated levels' do
level0_id = rubric.levels[0].id
level1_mark, level1_name, level1_id = rubric.levels[1].mark, rubric.levels[1].name, rubric.levels[1].id

params = {
'0' => { name: level1_name, mark: level1_mark, id: level0_id },
'1' => { name: level1_name, mark: level1_mark, id: level1_id }
}
level0_before = rubric.levels.find_by(id: level0_id)
level1_before = rubric.levels.find_by(id: level1_id)
rubric.update_levels(params)

expect(rubric.levels.find_by(id: level0_id)).to eq(level0_before)
expect(rubric.levels.find_by(id: level1_id)).to eq(level1_before)
end
end
end
end

context 'A good rubric criterion model' do
before do
@rubric = create(:rubric_criterion)
Expand Down