From 60dcac209ca63813ca593b7900467bd447808411 Mon Sep 17 00:00:00 2001 From: Alex Dolski Date: Thu, 4 Jan 2024 16:09:19 -0600 Subject: [PATCH] Add collection_handles column to CSV --- app/util/csv_exporter.rb | 16 +- app/util/csv_importer.rb | 119 ++++++++-- test/fixtures/files/csv/illegal_element.csv | 4 +- test/fixtures/files/csv/new.csv | 4 +- .../packages/csv/missing_file/package.csv | 4 +- .../packages/csv/valid_items/package.csv | 6 +- test/fixtures/handles.yml | 38 +-- test/jobs/import_job_test.rb | 6 +- test/util/csv_importer_test.rb | 222 ++++++++++++++++-- 9 files changed, 351 insertions(+), 68 deletions(-) diff --git a/app/util/csv_exporter.rb b/app/util/csv_exporter.rb index 097f741c..94256ba2 100644 --- a/app/util/csv_exporter.rb +++ b/app/util/csv_exporter.rb @@ -121,7 +121,17 @@ def export_unit(unit, elements: []) # @return [String] # def select_clause(elements) - columns = ["items.id", "handles.suffix"] + columns = ["items.id", "item_handles.suffix AS item_handle"] + # collection_handles column + columns << "array_to_string( + array( + SELECT CONCAT('#{Handle.prefix}/', h.suffix) AS suffix + FROM handles h + LEFT JOIN collection_item_memberships cim ON cim.item_id = items.id + WHERE cim.item_id = items.id + AND h.collection_id = cim.collection_id + ORDER BY cim.primary DESC NULLS LAST + ), '||') AS collection_handles\n" # files column columns << "array_to_string( array( @@ -192,7 +202,7 @@ def from_clause end def join_clauses - "LEFT JOIN handles ON handles.item_id = items.id\n" + + "LEFT JOIN handles item_handles ON item_handles.item_id = items.id\n" + "LEFT JOIN collection_item_memberships cim ON cim.item_id = items.id " end @@ -209,4 +219,4 @@ def to_csv(elements, results) end end -end \ No newline at end of file +end diff --git a/app/util/csv_importer.rb b/app/util/csv_importer.rb index b0b45d24..63bbd2e0 100644 --- a/app/util/csv_importer.rb +++ b/app/util/csv_importer.rb @@ -29,14 +29,27 @@ # # The first column, `id`, refers to an item's internal database ID. The second # column, `handle`, refers to an item's handle. (These columns cannot be -# modified.) The next several columns refer to various system-level item -# properties. The remaining columns correspond to the elements in the effective +# modified.) +# +# The third column, `collection_handles`, refers to the handles of the +# collections to which the item belongs. There may be multiple handles listed +# in this column, separated by a double pipe (`||`), as an item may belong to +# multiple collections. If this is the case, the first handle listed will +# correspond to the item's primary collection. Whether or not there are +# multiple handles, the first handle in this column must match that of the +# collection associated with the import. +# +# The next several columns refer to various other item properties +# These columns are collectively listed in {CsvImporter#REQUIRED_COLUMNS}. +# +# The remaining columns correspond to the elements in the effective # {MetadataProfile} of the collection that apply to the item. # -# All columns are required except metadata columns. When a metadata column is -# missing, the corresponding metadata elements of the items in the CSV file -# will be left unchanged. For new items in the CSV file, a missing metadata -# column may be an error depending on whether it is required or not. +# All columns are required to exist (even if empty) except metadata columns. +# When a metadata column is missing, the corresponding metadata elements of the +# items in the CSV file will be left unchanged. For new items in the CSV file, +# a missing metadata column may be an error depending on whether it is required +# or not. # # ## Non-header rows # @@ -48,6 +61,13 @@ # # The next group of cells correspond to various system properties of the item: # +# * `handle` The item's handle. This is for informational +# purposes only--it cannot be updated by +# changing the value. +# * `collection_handle` The handle of the item's owning {Collection}. +# Changing the value to the handle of some other +# collection will cause the item to be moved +# into it. # * `files` Names of all files attached to an item. For # uploads, this may be a path relative to a # package root in which the CSV resides. @@ -113,11 +133,12 @@ # class CsvImporter - MULTI_VALUE_DELIMITER = "||" - NEW_ITEM_INDICATOR = "+" - REQUIRED_COLUMNS = %w[id handle files file_descriptions embargo_types - embargo_expirations embargo_exempt_user_groups - embargo_reasons] + MULTI_VALUE_DELIMITER = "||" + NEW_ITEM_INDICATOR = "+" + REQUIRED_COLUMNS = %w[id handle collection_handles files + file_descriptions embargo_types + embargo_expirations embargo_exempt_user_groups + embargo_reasons] ## # Imports items from a CSV string. @@ -126,8 +147,12 @@ class CsvImporter # @param file_paths [Enumerable] Absolute paths of files that are # referenced in the CSV's `files` # column. - # @param submitter [User] - # @param primary_collection [Collection] Collection to import new items into. + # @param submitter [User] The user performing the import. + # @param primary_collection [Collection] Collection associated with the + # import. This may be the collection + # that items are added to if it is + # not overridden by the + # `collection_handles` column. # @param imported_items [Array] For each imported item, whether # created or updated, a hash # containing `:item_id` and `:handle` @@ -144,6 +169,9 @@ def import(pathname:, imported_items: [], print_progress: false, task: nil) + raise ArgumentError, "Pathname is nil" unless pathname + raise ArgumentError, "File does not exist: #{pathname}" unless File.exist?(pathname) + raise ArgumentError, "Nil submitter argument" unless submitter num_rows = 0 File.foreach(pathname) do num_rows += 1 @@ -174,18 +202,19 @@ def import(pathname:, file_paths: file_paths) else item = Item.find(item_id) - item = update_item(item: item, - submitter: submitter, - element_names: header_row[REQUIRED_COLUMNS.length..], - row: row, - file_paths: file_paths) + item = update_item(item: item, + submitter: submitter, + primary_collection: primary_collection, + element_names: header_row[REQUIRED_COLUMNS.length..], + row: row, + file_paths: file_paths) end imported_items << { item_id: item.id, handle: item.handle&.handle } status_text = "Importing #{num_rows} items from CSV" - row_index += 1 + row_index += 1 progress&.report(row_index, status_text) task&.progress(row_index / (num_rows - 1).to_f, status_text: status_text) @@ -213,6 +242,10 @@ def create_item(submitter:, stage: Item::Stages::APPROVED, event_description: "Item imported from CSV.").execute item.assign_handle + move_into_collections(item: item, + primary_collection: primary_collection, + collection_handles: row[2], + submitter: submitter) associate_bitstreams(item: item, row: row, file_paths: file_paths) if file_paths @@ -227,12 +260,17 @@ def create_item(submitter:, def update_item(item:, submitter:, + primary_collection:, element_names:, row:, - file_paths: nil) + file_paths: nil) UpdateItemCommand.new(item: item, user: submitter, description: "Updated via CSV").execute do + move_into_collections(item: item, + primary_collection: primary_collection, + collection_handles: row[2], + submitter: submitter) associate_bitstreams(item: item, row: row, file_paths: file_paths) @@ -350,6 +388,45 @@ def associate_embargoes(item:, row:) end end + ## + # @param item [Item] Item to move. + # @param primary_collection [Collection] Collection associated with the + # import. + # @param collection_handles [String] Value of the `collection_handles` + # column. + # @param submitter [User] User performing the import. + # + def move_into_collections(item:, + primary_collection:, + collection_handles:, + submitter:) + return if collection_handles.blank? + collection_handles = collection_handles.split(MULTI_VALUE_DELIMITER) + return if collection_handles.empty? + item.collection_item_memberships.destroy_all + collection_handles.each_with_index do |handle, index| + suffix = handle.split("/").last.strip + handle = Handle.find_by_suffix(suffix) + unless handle + raise ArgumentError, "Collection with handle #{handle} does not exist" + end + collection = handle.collection + if index == 0 && collection != primary_collection + raise ArgumentError, "The first handle in the collection_handles "\ + "column must be that of the collection "\ + "associated with the import" + end + unless submitter.effective_collection_admin?(collection) + raise ArgumentError, "User #{submitter} does not have permission to "\ + "add items to #{collection.title}" + end + unless item.collections.include?(collection) + item.collection_item_memberships.build(collection: handle.collection, + primary: index == 0).save! + end + end + end + ## # @param row [Hash] # @param submission_profile [SubmissionProfile] @@ -364,7 +441,7 @@ def validate_header(row:, submission_profile:) end REQUIRED_COLUMNS.each_with_index do |column, index| if row[index] != column - raise ArgumentError, "Missing #{column} column" + raise ArgumentError, "Missing #{column} column (expected at position #{index + 1})" end end end diff --git a/test/fixtures/files/csv/illegal_element.csv b/test/fixtures/files/csv/illegal_element.csv index 898ee2d5..2a494b09 100644 --- a/test/fixtures/files/csv/illegal_element.csv +++ b/test/fixtures/files/csv/illegal_element.csv @@ -1,2 +1,2 @@ -id,handle,files,file_descriptions,embargo_types,embargo_expirations,embargo_exempt_user_groups,embargo_reasons,bogus -+,"","","","","","","",Value of bogus element \ No newline at end of file +id,handle,collection_handles,files,file_descriptions,embargo_types,embargo_expirations,embargo_exempt_user_groups,embargo_reasons,bogus ++,"","","","","","","","",Value of bogus element \ No newline at end of file diff --git a/test/fixtures/files/csv/new.csv b/test/fixtures/files/csv/new.csv index 5638684f..d819f352 100644 --- a/test/fixtures/files/csv/new.csv +++ b/test/fixtures/files/csv/new.csv @@ -1,2 +1,2 @@ -id,handle,files,file_descriptions,embargo_types,embargo_expirations,embargo_exempt_user_groups,embargo_reasons,dc:title -+,"",hello.txt,"","","","","",New CSV Item \ No newline at end of file +id,handle,collection_handles,files,file_descriptions,embargo_types,embargo_expirations,embargo_exempt_user_groups,embargo_reasons,dc:title ++,"","",hello.txt,"","","","","",New CSV Item \ No newline at end of file diff --git a/test/fixtures/files/packages/csv/missing_file/package.csv b/test/fixtures/files/packages/csv/missing_file/package.csv index 153efad7..dbbfd62b 100644 --- a/test/fixtures/files/packages/csv/missing_file/package.csv +++ b/test/fixtures/files/packages/csv/missing_file/package.csv @@ -1,2 +1,2 @@ -id,handle,filenames,file_descriptions,embargo_types,embargo_expirations,embargo_exempt_user_groups,embargo_reasons,dc:title,dc:subject,dc:creator,dc:contributor,dc:description:abstract,dc:date:issued,dc:identifier:uri,dc:type -+,"",missing.txt,Hello world,"","","","",New Item 1,Subject 1||Subject 2,,,,,, +id,handle,collection_handles,filenames,file_descriptions,embargo_types,embargo_expirations,embargo_exempt_user_groups,embargo_reasons,dc:title,dc:subject,dc:creator,dc:contributor,dc:description:abstract,dc:date:issued,dc:identifier:uri,dc:type ++,"","",missing.txt,Hello world,"","","","",New Item 1,Subject 1||Subject 2,,,,,, diff --git a/test/fixtures/files/packages/csv/valid_items/package.csv b/test/fixtures/files/packages/csv/valid_items/package.csv index 27a4f44c..dc421d24 100644 --- a/test/fixtures/files/packages/csv/valid_items/package.csv +++ b/test/fixtures/files/packages/csv/valid_items/package.csv @@ -1,3 +1,3 @@ -id,handle,files,file_descriptions,embargo_types,embargo_expirations,embargo_exempt_user_groups,embargo_reasons,dc:title,dc:subject,dc:creator,dc:contributor,dc:description:abstract,dc:date:issued,dc:identifier:uri,dc:type -+,,item1/hello.txt||item1/license.txt,Hello world||License file,,,,,New Item 1,Subject 1||Subject 2,,,,,, -+,,item2/hello.txt||item2/license.txt,Hello world||License file,0||1,2045-02-05||2055-03-10,sysadmin||,Reason 1||Reason 2,New Item 2,Subject 1||Subject 2,,,,,, \ No newline at end of file +id,handle,collection_handles,files,file_descriptions,embargo_types,embargo_expirations,embargo_exempt_user_groups,embargo_reasons,dc:title,dc:subject,dc:creator,dc:contributor,dc:description:abstract,dc:date:issued,dc:identifier:uri,dc:type ++,,,item1/hello.txt||item1/license.txt,Hello world||License file,,,,,New Item 1,Subject 1||Subject 2,,,,,, ++,,,item2/hello.txt||item2/license.txt,Hello world||License file,0||1,2045-02-05||2055-03-10,sysadmin||,Reason 1||Reason 2,New Item 2,Subject 1||Subject 2,,,,,, \ No newline at end of file diff --git a/test/fixtures/handles.yml b/test/fixtures/handles.yml index 974bdc9e..5119224c 100644 --- a/test/fixtures/handles.yml +++ b/test/fixtures/handles.yml @@ -2,11 +2,11 @@ southwest_unit1_collection1: collection: southwest_unit1_collection1 - suffix: 5014 + suffix: 5000 southwest_unit1_collection1_item1: item: southwest_unit1_collection1_item1 - suffix: 5000 + suffix: 5001 ################################### southeast #################################### @@ -14,54 +14,62 @@ southwest_unit1_collection1_item1: southeast_collection1: collection: southeast_collection1 - suffix: 5001 + suffix: 5002 + +southeast_collection2: + collection: southeast_collection2 + suffix: 5003 + +southeast_empty: + collection: southeast_empty + suffix: 5004 # item handles southeast_item1: item: southeast_item1 - suffix: 5002 + suffix: 5005 southeast_approved: item: southeast_approved - suffix: 5003 + suffix: 5006 southeast_awaiting_ingest_into_medusa: item: southeast_awaiting_ingest_into_medusa - suffix: 5004 + suffix: 5007 southeast_in_medusa: item: southeast_in_medusa - suffix: 5005 + suffix: 5008 southeast_described: item: southeast_described - suffix: 5006 + suffix: 5009 southeast_embargoed: item: southeast_embargoed - suffix: 5007 + suffix: 5010 southeast_undescribed: item: southeast_undescribed - suffix: 5008 + suffix: 5011 southeast_submitting: item: southeast_submitting - suffix: 5009 + suffix: 5012 southeast_withdrawn: item: southeast_withdrawn - suffix: 5010 + suffix: 5013 southeast_buried: item: southeast_buried - suffix: 5011 + suffix: 5014 southeast_multiple_bitstreams: item: southeast_multiple_bitstreams - suffix: 5012 + suffix: 5015 southeast_collection1_collection1_item1: item: southeast_collection1_collection1_item1 - suffix: 5013 + suffix: 5016 diff --git a/test/jobs/import_job_test.rb b/test/jobs/import_job_test.rb index 5dce470c..1e3b230e 100644 --- a/test/jobs/import_job_test.rb +++ b/test/jobs/import_job_test.rb @@ -58,7 +58,8 @@ class ImportJobTest < ActiveSupport::TestCase ObjectStore.instance.put_object(key: import.file_key, path: fixture) - format = ImportJob.perform_now(import: import) + format = ImportJob.perform_now(import: import, + user: users(:southeast_admin)) assert_equal Import::Format::CSV_FILE, format end @@ -72,7 +73,8 @@ class ImportJobTest < ActiveSupport::TestCase ObjectStore.instance.put_object(key: import.file_key, path: csv_package) - format = ImportJob.perform_now(import: import) + format = ImportJob.perform_now(import: import, + user: users(:southeast_admin)) assert_equal Import::Format::CSV_PACKAGE, format end diff --git a/test/util/csv_importer_test.rb b/test/util/csv_importer_test.rb index ae75e4f2..bba00a15 100644 --- a/test/util/csv_importer_test.rb +++ b/test/util/csv_importer_test.rb @@ -14,6 +14,62 @@ class CsvImporterTest < ActiveSupport::TestCase # import() + test "import() raises an error for a missing pathname argument" do + assert_raises ArgumentError do + @instance.import(pathname: nil, + file_paths: [], + submitter: users(:southwest_sysadmin), + primary_collection: collections(:southeast_empty)) + end + end + + test "import() raises an error for a pathname that does not exist" do + assert_raises ArgumentError do + @instance.import(pathname: "/bogus/bogus/bogus.csv", + file_paths: [], + submitter: users(:southwest_sysadmin), + primary_collection: collections(:southeast_empty)) + end + end + + test "import() raises an error for a missing submitter argument" do + csv = CSV.generate do |row| + row << CsvImporter::REQUIRED_COLUMNS - %w[files] + end + file = Tempfile.new(%w[test, .csv]) + File.write(file, csv) + + assert_raises ArgumentError do + @instance.import(pathname: file.path, + file_paths: [], + submitter: nil, + primary_collection: collections(:southeast_empty)) + end + ensure + file.unlink + end + + test "import() raises an error when the first handle in the + collection_handles column is different from the primary_collection + argument" do + csv = CSV.generate do |row| + row << CsvImporter::REQUIRED_COLUMNS + row << ["+", nil, handles(:southeast_collection2).to_s, + nil, nil, nil, nil, nil, nil, "Title"] + end + file = Tempfile.new(%w[test, .csv]) + File.write(file, csv) + + assert_raises ArgumentError do + @instance.import(pathname: file.path, + file_paths: [], + submitter: users(:southeast_admin), + primary_collection: collections(:southeast_collection1)) + end + ensure + file.unlink + end + test "import() raises an error for a missing id column" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS - %w[id] @@ -30,6 +86,38 @@ class CsvImporterTest < ActiveSupport::TestCase file.unlink end + test "import() raises an error for a missing handle column" do + csv = CSV.generate do |row| + row << CsvImporter::REQUIRED_COLUMNS - %w[handle] + end + file = Tempfile.new(%w[test, .csv]) + File.write(file, csv) + + assert_raises ArgumentError do + @instance.import(pathname: file.path, + submitter: users(:southwest_sysadmin), + primary_collection: collections(:southeast_empty)) + end + ensure + file.unlink + end + + test "import() raises an error for a missing collection_handles column" do + csv = CSV.generate do |row| + row << CsvImporter::REQUIRED_COLUMNS - %w[collection_handles] + end + file = Tempfile.new(%w[test, .csv]) + File.write(file, csv) + + assert_raises ArgumentError do + @instance.import(pathname: file.path, + submitter: users(:southwest_sysadmin), + primary_collection: collections(:southeast_empty)) + end + ensure + file.unlink + end + test "import() raises an error for a missing files column" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS - %w[files] @@ -131,7 +219,7 @@ class CsvImporterTest < ActiveSupport::TestCase is required by the submission profile" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS - row << ["+", nil, nil, nil, nil, nil, nil, nil] + row << ["+", nil, nil, nil, nil, nil, nil, nil, nil] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -149,7 +237,7 @@ class CsvImporterTest < ActiveSupport::TestCase required by the submission profile" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << ["+", nil, nil, nil, nil, nil, nil, nil, ""] + row << ["+", nil, nil, nil, nil, nil, nil, nil, nil, ""] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -166,7 +254,7 @@ class CsvImporterTest < ActiveSupport::TestCase test "import() parses multi-value elements correctly" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title dc:creator] - row << ["+", nil, nil, nil, nil, nil, nil, nil, "Title", "Bob||Susan||Chris"] + row << ["+", nil, nil, nil, nil, nil, nil, nil, nil, "Title", "Bob||Susan||Chris"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -187,7 +275,7 @@ class CsvImporterTest < ActiveSupport::TestCase test "import() assigns positions to multi-value elements" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title dc:creator] - row << ["+", nil, nil, nil, nil, nil, nil, nil, "Title", "Bob||Susan||Chris"] + row << ["+", nil, nil, nil, nil, nil, nil, nil, nil, "Title", "Bob||Susan||Chris"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -212,7 +300,7 @@ class CsvImporterTest < ActiveSupport::TestCase test "import() creates a new item" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << ["+", nil, nil, nil, nil, nil, nil, nil, "New Item"] + row << ["+", nil, nil, nil, nil, nil, nil, nil, nil, "New Item"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -240,6 +328,104 @@ class CsvImporterTest < ActiveSupport::TestCase end end + test "import() places a new item into the collections given in the + collection_handles column" do + collection1 = collections(:southeast_collection1) + collection2 = collections(:southeast_collection2) + csv = CSV.generate do |row| + row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title dc:creator] + row << ["+", nil, + [collection1.handle.to_s, collection2.handle.to_s].join(CsvImporter::MULTI_VALUE_DELIMITER), + nil, nil, nil, nil, nil, nil, "Title", "Bob"] + end + file = Tempfile.new(%w[test, .csv]) + File.write(file, csv) + + @instance.import(pathname: file.path, + file_paths: [], + submitter: users(:southeast_admin), + primary_collection: collection1) + item = Item.order(created_at: :desc).limit(1).first + assert_equal 2, item.collection_item_memberships.count + assert_equal collection1, item.effective_primary_collection + assert item.collections.include?(collection2) + ensure + file.unlink + end + + test "import() moves an existing item into the collections given in the + collection_handles column" do + item = items(:southeast_approved) + item.collection_item_memberships.destroy_all + new_collection1 = collections(:southeast_collection1) + new_collection2 = collections(:southeast_collection2) + + csv = CSV.generate do |row| + row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title dc:creator] + row << [item.id, nil, + [new_collection1.handle.to_s, new_collection2.handle.to_s].join(CsvImporter::MULTI_VALUE_DELIMITER), + nil, nil, nil, nil, nil, nil, "Title", "Bob"] + end + file = Tempfile.new(%w[test, .csv]) + File.write(file, csv) + + @instance.import(pathname: file.path, + file_paths: [], + submitter: users(:southeast_admin), + primary_collection: new_collection1) + item.reload + assert_equal new_collection1, item.effective_primary_collection + assert item.collections.include?(new_collection2) + ensure + file.unlink + end + + test "import() raises an error when asked to place a new item into a + collection of which the submitter is not a manager" do + collection = collections(:southeast_collection1) + csv = CSV.generate do |row| + row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title dc:creator] + row << ["+", nil, collection.handle.to_s, + nil, nil, nil, nil, nil, nil, "Title", "Bob"] + end + file = Tempfile.new(%w[test, .csv]) + File.write(file, csv) + + assert_raises ArgumentError do + @instance.import(pathname: file.path, + file_paths: [], + submitter: users(:southeast), + primary_collection: collection) + end + ensure + file.unlink + end + + test "import() raises an error when asked to move an existing item into a + collection of which the submitter is not a manager" do + item = items(:southeast_approved) + current_collection = item.effective_primary_collection + new_collection = collections(:southeast_empty) + assert_not_equal new_collection, current_collection + + csv = CSV.generate do |row| + row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title dc:creator] + row << ["+", nil, new_collection.handle.to_s, + nil, nil, nil, nil, nil, nil, "Title", "Bob"] + end + file = Tempfile.new(%w[test, .csv]) + File.write(file, csv) + + assert_raises ArgumentError do + @instance.import(pathname: file.path, + file_paths: [], + submitter: users(:southeast), + primary_collection: new_collection) + end + ensure + file.unlink + end + test "import() attaches Bitstreams to new items" do package_path = File.join(file_fixture_path, "packages", "csv", "valid_items") csv_path = File.join(package_path, "package.csv") @@ -267,7 +453,7 @@ class CsvImporterTest < ActiveSupport::TestCase item = items(:southwest_unit1_collection1_item1) csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << [item.id, nil, "escher_lego.png", nil, nil, nil, nil, nil, "Title"] + row << [item.id, nil, nil, "escher_lego.png", nil, nil, nil, nil, nil, "Title"] end files = [file_fixture("escher_lego.png").to_s] file = Tempfile.new(%w[test, .csv]) @@ -289,7 +475,7 @@ class CsvImporterTest < ActiveSupport::TestCase files = %w[gull.jpg pooh.jpg] csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << [item.id, nil, files.join("||"), nil, nil, nil, nil, nil, "Title"] + row << [item.id, nil, nil, files.join("||"), nil, nil, nil, nil, nil, "Title"] end files = files.map{ |f| file_fixture(f).to_s } file = Tempfile.new(%w[test, .csv]) @@ -315,7 +501,7 @@ class CsvImporterTest < ActiveSupport::TestCase files = %w[gull.jpg pooh.jpg] csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << [item.id, nil, files.join("||"), nil, nil, nil, nil, nil, "Title"] + row << [item.id, nil, nil, files.join("||"), nil, nil, nil, nil, nil, "Title"] end files = files.map{ |f| file_fixture(f).to_s } file = Tempfile.new(%w[test, .csv]) @@ -338,7 +524,7 @@ class CsvImporterTest < ActiveSupport::TestCase item = items(:southwest_unit1_collection1_item1) csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << [item.id, nil, "approved.png", nil, nil, nil, nil, nil, "Title"] + row << [item.id, nil, nil, "approved.png", nil, nil, nil, nil, nil, "Title"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -377,7 +563,7 @@ class CsvImporterTest < ActiveSupport::TestCase test "import() adds created items to the imported_items array" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << ["+", nil, nil, nil, nil, nil, nil, nil, "New Item"] + row << ["+", nil, nil, nil, nil, nil, nil, nil, nil, "New Item"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -397,7 +583,7 @@ class CsvImporterTest < ActiveSupport::TestCase CSV" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[bogus:bogus] - row << ["+", nil, nil, nil, nil, nil, nil, nil, "New Value"] + row << ["+", nil, nil, nil, nil, nil, nil, nil, nil, "New Value"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -415,7 +601,7 @@ class CsvImporterTest < ActiveSupport::TestCase CSV" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << ["999999", nil, nil, nil, nil, nil, nil, "New Value"] + row << ["999999", nil, nil, nil, nil, nil, nil, nil, "New Value"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -433,7 +619,7 @@ class CsvImporterTest < ActiveSupport::TestCase test "import() raises an error for a blank item ID cell" do csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << [nil, nil, nil, nil, nil, nil, nil, "New Value"] + row << [nil, nil, nil, nil, nil, nil, nil, nil, "New Value"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -451,7 +637,7 @@ class CsvImporterTest < ActiveSupport::TestCase item = items(:southeast_item1) csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << [item.id, nil, nil, nil, nil, nil, nil, nil, "New Title"] + row << [item.id, nil, nil, nil, nil, nil, nil, nil, nil, "New Title"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -470,7 +656,7 @@ class CsvImporterTest < ActiveSupport::TestCase item = items(:southeast_described) csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title dc:subject] - row << [item.id, nil, nil, nil, nil, nil, nil, nil, "Title", ""] + row << [item.id, nil, nil, nil, nil, nil, nil, nil, nil, "Title", ""] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -490,7 +676,7 @@ class CsvImporterTest < ActiveSupport::TestCase item = items(:southeast_described) csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << [item.id, nil, nil, nil, nil, nil, nil, nil, "New Title"] + row << [item.id, nil, nil, nil, nil, nil, nil, nil, nil, "New Title"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -511,7 +697,7 @@ class CsvImporterTest < ActiveSupport::TestCase task = tasks(:pending) csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[dc:title] - row << [item.id, nil, nil, nil, nil, nil, nil, nil, "New Title"] + row << [item.id, nil, nil, nil, nil, nil, nil, nil, nil, "New Title"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv) @@ -532,7 +718,7 @@ class CsvImporterTest < ActiveSupport::TestCase task = tasks(:pending) csv = CSV.generate do |row| row << CsvImporter::REQUIRED_COLUMNS + %w[bogus:bogus] - row << [item.id, nil, nil, nil, nil, nil, nil, "Bogus element value"] + row << [item.id, nil, nil, nil, nil, nil, nil, nil, "Bogus element value"] end file = Tempfile.new(%w[test, .csv]) File.write(file, csv)