- Create Assessment record in UI
- Create new Assessment record via API
- Mitigating assessments that got created with unwanted ratings
Testing creating an Assessment with an assessment_attribute note, but no rating (value) for the assessment_attribute.
In the UI, create new assessment with NO RATING for Documentation quality AND a NOTE for Documentation quality:
bin/console in aspace-data-tools:
c = ADT.client
a = c.get("/repositories/2/assessments/2")
a.parsed
=> {"lock_version" => 1,
"accession_report" => false,
"appraisal" => false,
"container_list" => false,
"catalog_record" => false,
"control_file" => false,
"finding_aid_ead" => false,
"finding_aid_paper" => false,
"finding_aid_word" => false,
"finding_aid_spreadsheet" => false,
"review_required" => false,
"sensitive_material" => false,
"general_assessment_note" => "My general assessment note",
"deed_of_gift" => false,
"finding_aid_online" => false,
"related_eac_records" => false,
"survey_begin" => "2026-09-30",
"inactive" => false,
"created_by" => "admin",
"last_modified_by" => "admin",
"create_time" => "2026-09-30T20:22:36Z",
"system_mtime" => "2026-09-30T20:26:48Z",
"user_mtime" => "2026-09-30T20:26:48Z",
"jsonmodel_type" => "assessment",
"records" => [{"ref" => "/repositories/2/accessions/1"}],
"surveyed_by" => [{"ref" => "/agents/people/26"}],
"reviewer" => [],
"formats" =>
[{"global" => true, "label" => "Architectural Materials", "readonly" => false, "definition_id" => 9},
{"global" => true, "label" => "Art Originals", "readonly" => false, "definition_id" => 10},
{"global" => true, "label" => "Artifacts", "readonly" => false, "definition_id" => 11},
{"global" => true, "label" => "Audio Materials", "readonly" => false, "definition_id" => 12},
{"global" => true, "label" => "Biological Specimens", "readonly" => false, "definition_id" => 13},
{"global" => true, "label" => "Botanical Specimens", "readonly" => false, "definition_id" => 14},
{"global" => true, "label" => "Computer Storage Units", "readonly" => false, "definition_id" => 15},
{"global" => true, "label" => "Film (negative, slide, or motion picture)", "readonly" => false, "definition_id" => 16},
{"global" => true, "label" => "Glass", "readonly" => false, "definition_id" => 17},
{"global" => true, "label" => "Photographs", "readonly" => false, "definition_id" => 18},
{"global" => true, "label" => "Scrapbooks", "readonly" => false, "definition_id" => 19},
{"global" => true, "label" => "Technical Drawings & Schematics", "readonly" => false, "definition_id" => 20},
{"global" => true, "label" => "Textiles", "readonly" => false, "definition_id" => 21},
{"global" => true, "label" => "Vellum & Parchment", "readonly" => false, "definition_id" => 22},
{"global" => true, "label" => "Video Materials", "readonly" => false, "definition_id" => 23},
{"global" => true, "label" => "Other", "readonly" => false, "definition_id" => 24}],
"conservation_issues" =>
[{"global" => true, "label" => "Potential Mold or Mold Damage", "readonly" => false, "definition_id" => 25},
{"global" => true, "label" => "Recent Pest Damage", "readonly" => false, "definition_id" => 26},
{"global" => true, "label" => "Deteriorating Film Base", "readonly" => false, "definition_id" => 27},
{"global" => true, "label" => "Brittle Paper", "readonly" => false, "definition_id" => 28},
{"global" => true, "label" => "Metal Fasteners", "readonly" => false, "definition_id" => 29},
{"global" => true, "label" => "Newspaper", "readonly" => false, "definition_id" => 30},
{"global" => true, "label" => "Tape", "readonly" => false, "definition_id" => 31},
{"global" => true, "label" => "Heat-Sensitive Paper", "readonly" => false, "definition_id" => 32},
{"global" => true, "label" => "Water Damage", "readonly" => false, "definition_id" => 33}],
"ratings" =>
[{"global" => true, "label" => "Reformatting Readiness", "readonly" => false, "definition_id" => 1},
{"global" => true, "label" => "Housing Quality", "readonly" => false, "definition_id" => 2},
{"global" => true, "label" => "Physical Condition", "readonly" => false, "definition_id" => 3},
{"global" => true, "label" => "Physical Access (arrangement)", "readonly" => false, "definition_id" => 4},
{"global" => true, "label" => "Intellectual Access (description)", "readonly" => false, "definition_id" => 5},
{"global" => true, "label" => "Interest", "readonly" => false, "definition_id" => 6},
{"global" => true, "label" => "Documentation Quality", "note" => "My documentation quality note", "readonly" => false, "definition_id" => 7},
{"global" => true, "label" => "Research Value", "readonly" => true, "definition_id" => 8}],
"external_documents" => [],
"collections" => [],
"uri" => "/repositories/2/assessments/2",
"repository" => {"ref" => "/repositories/2"},
"display_string" => "2"}
My assessment record is stored:
The assessment attribute note is stored:
PERHAPS IMPORTANT: No rows for any attributes are written to the assessment_attribute table:
I created a new asmt.json (attached as separate file) file based off the result of my api call.
Back in aspace-data-tools console:
json = JSON.load_file(File.join(Bundler.root, "asmt.json"))
=> (a big JSON output)
result = c.post("/repositories/2/assessments", json)
=> #<ArchivesSpace::Response:0x0000000124c544d0
@body="{\"status\":\"Created\",\"id\":3,\"lock_version\":0,\"stale\":null,\"uri\":\"/repositories/2/assessments/3\",\"warnings\":[]}\n",
@headers=
{"connection" => ["close"],
"date" => ["Wed, 30 Sep 2026 21:01:52 GMT"],
"content-type" => ["application/json"],
"cache-control" => ["private, must-revalidate, max-age=0"],
"x-content-type-options" => ["nosniff"],
"content-length" => ["110"],
"server" => ["Jetty(9.4.44.v20210927)"]},
@parsed={"status" => "Created", "id" => 3, "lock_version" => 0, "stale" => nil, "uri" => "/repositories/2/assessments/3", "warnings" => []},
@result={"status" => "Created", "id" => 3, "lock_version" => 0, "stale" => nil, "uri" => "/repositories/2/assessments/3", "warnings" => []},
@status=#<Net::HTTPOK 200 OK readbody=true>,
@status_code=200>
New assessment row with id = 3 created.
Documentation quality note created exactly as for assessment 2
No assessment_attribute rows create for this record
IN UI, record looks like I expect it to:
Leaving the non-note column for the assessment attribute empty works:
basic,basic,basic,basic,rating,rating
record,record,surveyed_by,survey_begin,Reformatting Readiness,Reformatting Readiness_note
accession_1,,admin,2017-07-04,,test
This gets the error: Errors: #<JSONModel::ModelNotFound: JSONModel not found for rating_reformatting_readiness>:
basic,basic,basic,basic,rating
record,record,surveyed_by,survey_begin,Reformatting Readiness_note
accession_1,,admin,2017-07-04,test
AssessmentConverter.configure does not itself throw this error. [src]
It produces the following config Hash:
[java] => {:records_1=>
[java] {:record_type=>#<Proc:0x55fdf5fa /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:87>,
[java] :on_row_complete=>#<Proc:0x552d5a7 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:90>},
[java] "basic_record_1"=>[#<Proc:0x136a0854 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:266>, "records_1.uri"],
[java] :records_2=>
[java] {:record_type=>#<Proc:0x2cbb0969 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:87>,
[java] :on_row_complete=>#<Proc:0x3c6bfa74 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:90>},
[java] "basic_record_2"=>[#<Proc:0x136a0854 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:266>, "records_2.uri"],
[java] :agents_1=>
[java] {:record_type=>#<Proc:0x749b6e76 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:108>,
[java] :on_row_complete=>#<Proc:0x1e3a139a /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:111>},
[java] "basic_surveyed_by_1"=>[#<Proc:0x1b51b0bd /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:287>, "agents_1.uri"],
[java] "basic_survey_begin"=>[#<Proc:0x503b8e11 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:236>, "assessment.survey_begin"],
[java] "rating_reformatting_readiness_note"=>[nil, "rating_reformatting_readiness.note"]}
I have no idea what this is supposed to look like, so I pulled it for the job that works:
[java] => {:records_1=>
[java] {:record_type=>#<Proc:0x101d40e5 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:87>,
[java] :on_row_complete=>#<Proc:0xf760b83 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:90>},
[java] "basic_record_1"=>[#<Proc:0x136a0854 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:266>, "records_1.uri"],
[java] :records_2=>
[java] {:record_type=>#<Proc:0x64424277 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:87>,
[java] :on_row_complete=>#<Proc:0x7eed3131 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:90>},
[java] "basic_record_2"=>[#<Proc:0x136a0854 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:266>, "records_2.uri"],
[java] :agents_1=>
[java] {:record_type=>#<Proc:0x1a952014 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:108>,
[java] :on_row_complete=>#<Proc:0x14f216dd /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:111>},
[java] "basic_surveyed_by_1"=>[#<Proc:0x1b51b0bd /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:287>, "agents_1.uri"],
[java] "basic_survey_begin"=>[#<Proc:0x503b8e11 /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:236>, "assessment.survey_begin"],
[java] :rating_reformatting_readiness=>{:record_type=>"assessment_attribute", :on_row_complete=>#<Proc:0x1cf20e3f /Users/kristina/code/as/archivesspace/backend/app/converters/assessment_converter.rb:170>},
[java] "rating_reformatting_readiness"=>[nil, "rating_reformatting_readiness.value"],
[java] "rating_reformatting_readiness_note"=>[nil, "rating_reformatting_readiness.note"]}
So the presence of the Reformatting Readiness column causes the following to be added before the two rating fields:
:rating_reformatting_readiness => {:record_type=>"assessment_attribute", :on_row_complete=>#<Proc...>}
It made me itchy that the following key in this Hash is the same, but as a String instead of a Symbol!:
"rating_reformatting_readiness"=>[nil, "rating_reformatting_readiness.value"]
This is the eventual cause of the error, which doesn't get triggered until all of this is sent through CsvConverter.parse_row to RecordProxy.spawn, which attempts to create a JSONModel without the necessary data to do so, eg. the :record_type=>"assessment_attribute" in the missing Hash value for the Symbol :rating_reformatting_readiness.
Example in UI:
Deleting the assessment_attribute rows with funky values resets the display to: