Skip to content

Commit 66cc8f9

Browse files
authored
Merge pull request #418 from openstax/import-feedback
CORE-861 Added feedback columns to assessments spreadsheet import
2 parents 4be2162 + de6bd38 commit 66cc8f9

File tree

5 files changed

+45169
-6
lines changed

5 files changed

+45169
-6
lines changed

app/routines/exercises/import/assessments.rb

+28-5
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,16 @@ def exec(filename:, book_uuid:)
3434
record_failures do |failures|
3535
ProcessSpreadsheet.call(filename: filename, headers: :downcase) do |headers, row, row_index|
3636
uuid_index ||= headers.index { |header| header == 'uuid' || header == 'page uuid' }
37-
raise ArgumentError, 'Could not find page "UUID" column' if uuid_index.nil?
37+
38+
section_index ||= headers.index { |header| header == 'section' }
39+
raise ArgumentError, 'Could not find "UUID" or "Section" columns' if uuid_index.nil? && section_index.nil?
40+
41+
unless section_index.nil?
42+
book = OpenStax::Content::Abl.new.approved_books.find { |book| book.uuid == book_uuid }
43+
page_uuid_by_book_location = {}
44+
book.all_pages.each { |page| page_uuid_by_book_location[page.book_location] = page.uuid }
45+
raise ArgumentError, "Could not find book with UUID #{book_uuid} in the ABL" if book.nil?
46+
end
3847

3948
pre_or_post_index ||= headers.index { |header| header&.start_with?('pre') && header.end_with?('post') }
4049
raise ArgumentError, 'Could not find "Pre or Post" column' if pre_or_post_index.nil?
@@ -45,10 +54,14 @@ def exec(filename:, book_uuid:)
4554
raise ArgumentError, 'Could not find "Question Stem" column' if question_stem_index.nil?
4655

4756
answer_choice_indices ||= headers.filter_map.with_index do |header, index|
48-
index if header&.start_with?('answer') || header&.end_with?('choice')
57+
index if (header&.start_with?('answer') || header&.end_with?('choice')) && !header.include?('feedback')
4958
end
5059
raise ArgumentError, 'Could not find "Answer Choice" columns' if answer_choice_indices.empty?
5160

61+
feedback_indices ||= headers.filter_map.with_index do |header, index|
62+
index if header&.include?('feedback')
63+
end
64+
5265
correct_answer_index ||= headers.index { |header| header&.start_with?('correct') }
5366
raise ArgumentError, 'Could not find "Correct Answer" column' if correct_answer_index.nil?
5467

@@ -57,9 +70,14 @@ def exec(filename:, book_uuid:)
5770

5871
row_number = row_index + 1
5972

60-
page_uuid = row[uuid_index]
73+
page_uuid = if uuid_index.nil? || row[uuid_index].blank?
74+
page_uuid_by_book_location[row[section_index].split('.').map(&:to_i)] unless row[section_index].blank?
75+
else
76+
row[uuid_index]
77+
end
78+
6179
if page_uuid.blank?
62-
Rails.logger.info { "Skipped row ##{row_number} with blank page UUID" }
80+
Rails.logger.info { "Skipped row ##{row_number} with blank Section or Page UUID" }
6381
next
6482
end
6583

@@ -85,9 +103,14 @@ def exec(filename:, book_uuid:)
85103
answer_choice_indices.each_with_index do |row_index, answer_index|
86104
content = row[row_index]
87105
next if content.blank?
106+
107+
feedback_index = feedback_indices[answer_index]
108+
feedback = row[feedback_index] unless feedback_index.nil?
109+
88110
stem.stem_answers << StemAnswer.new(
89111
answer: Answer.new(question: question, content: parse(content, exercise)),
90-
correctness: answer_index == correct_answer ? 1 : 0
112+
correctness: answer_index == correct_answer ? 1 : 0,
113+
feedback: parse(feedback, exercise)
91114
)
92115
end
93116

app/routines/process_spreadsheet.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def exec(filename:, offset: 1, pad_cells: true, headers: false, &block)
1919
args = []
2020
pad_to_size = 0 if pad_cells
2121
klass.new(filename).public_send(method).each_with_index do |row, row_index|
22-
normalized_row = row.map { |value| value&.to_s&.strip }
22+
normalized_row = row.map { |cell| cell.value&.to_s&.strip }
2323

2424
if headers && row_index == 0
2525
header_row = normalized_row

spec/cassettes/Exercises_Import_Assessments/imports_exercises_from_the_spreadsheet_and_adds_Assignable_tags.yml

+45,095
Large diffs are not rendered by default.
10.5 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
require 'rails_helper'
2+
require 'vcr_helper'
3+
4+
RSpec.describe Exercises::Import::Assessments, type: :routine, vcr: VCR_OPTS do
5+
let(:book_uuid) { '62a49025-8cd8-407c-9cfb-c7eba55cf1c6' }
6+
let(:fixture_path) { 'spec/fixtures/sample_import_assessments.xlsx' }
7+
8+
it 'imports exercises from the spreadsheet and adds Assignable tags' do
9+
allow(User).to receive(:find) { FactoryBot.create :user, :agreed_to_terms }
10+
11+
allow_any_instance_of(OpenStax::Content::Book).to receive(:version).and_return('964da1b')
12+
13+
expect { described_class.call(book_uuid: book_uuid, filename: fixture_path) }.to change { Exercise.count }.by(2)
14+
15+
exercises = Exercise.order(:created_at).last(2)
16+
17+
expect(Set.new exercises[0].tags.map(&:to_s)).to eq Set[
18+
'assessment:preparedness:https://openstax.org/orn/book:page/62a49025-8cd8-407c-9cfb-c7eba55cf1c6:97af6b57-0004-4218-99c1-f2cfedea8f30',
19+
'context-cnxmod:97af6b57-0004-4218-99c1-f2cfedea8f30',
20+
'book-slug:college-success-concise',
21+
'book-slug:preparing-for-college-success',
22+
'module-slug:college-success-concise:1-1-why-college',
23+
'module-slug:preparing-for-college-success:2-1-why-college',
24+
]
25+
expect(exercises[0].questions.first.stems.first.content).to eq 'Some question?'
26+
expect(Set.new(exercises[0].questions.first.stems.first.stem_answers.map do |stem_answer|
27+
[stem_answer.answer.content, stem_answer.correctness.to_s, stem_answer.feedback]
28+
end)).to eq Set[['Right', '1.0', 'This is why A is correct'], ['Wrong', '0.0', 'This is why B is wrong']]
29+
expect(exercises[0].questions.first.collaborator_solutions.first.content).to eq 'Some solution'
30+
expect(exercises[0].publication.published_at?).to eq true
31+
32+
expect(Set.new exercises[1].tags.map(&:to_s)).to eq Set[
33+
'assessment:practice:https://openstax.org/orn/book:page/62a49025-8cd8-407c-9cfb-c7eba55cf1c6:6c30d0cc-e435-4081-be68-5ff2f558cbec',
34+
'context-cnxmod:6c30d0cc-e435-4081-be68-5ff2f558cbec',
35+
'book-slug:college-success',
36+
'module-slug:college-success:1-2-the-first-year-of-college-will-be-an-experience',
37+
]
38+
expect(exercises[1].questions.first.stems.first.content).to eq 'Another question?'
39+
expect(Set.new(exercises[1].questions.first.stems.first.stem_answers.map do |stem_answer|
40+
[stem_answer.answer.content, stem_answer.correctness.to_s, stem_answer.feedback]
41+
end)).to eq Set[['Not this one', '0.0', 'Better luck next time'], ['This one', '1.0', 'Good job']]
42+
expect(exercises[1].questions.first.collaborator_solutions.first.content).to eq 'Another solution'
43+
expect(exercises[1].publication.published_at?).to eq true
44+
end
45+
end

0 commit comments

Comments
 (0)