help needed: plugin creating a multi-select dropdown

17 views
Skip to first unread message

Ron Van den Branden

unread,
Nov 25, 2025, 3:37:42 PM (7 days ago) Nov 25
to archivesspac...@lyrasislists.org
Hi all,

I'm trying to create a plugin that adds a Material Types subrecord to Accessions, offering a multi-select dropdown describing materials of the accession, which dropdown is populated with values from a dynamic enumeration value list. For example a JSON structure like :

{
    "dynamaterial_type_list": {
    "dynamaterial_type": [
        "audiovisual_materials",
        "electronic_documents",
        "microforms"
    ]
}

...would populate a dropdown in a "Material Types" subrecord on the Accession edit form, from which the user can choose one or more values.

This plugin is inspired by https://github.com/hudmol/material_types, but tries to offer more flexibility by managing the "Material Types" in an editable controlled value list. The structure of this plugin is inspired on the only multiple value select example I could find in the ArchivesSpace codebase: Rights Restriction Notes in the Resources and Archival Objects (see https://github.com/archivesspace/archivesspace/blob/master/backend/app/model/mixins/rights_restriction_notes.rb)

I'm not a Ruby / Rails developer at all, but the documentation and examples in the ArchivesSpace technical documentation and Hello World plugin have helped me in hacking my way to a point where I dare to reach out for help. I've managed to set up the dynamic enumeration list, database tables, define the JSON models, display the field and values in the SUI (at least, for Material Type data stored directly in the db), and read the values submitted by the SUI form. Yet, I'm stuck at (what seems to me) the actual addition of these updated values to the Accession object, and storing it in the database. 

I have committed the current state of my endeavour to a Github repository at https://github.com/rvdb/aspace_material_types-dynamic/, in the hope someone wouldn't mind casting an eye and pointing me forward. Currently, I'm stuck at https://github.com/rvdb/aspace_material_types-dynamic/blob/main/backend/model/mixins/dynamaterial_type_record.rb#L63, which attempts to add  `dynamaterial_type_list` to the Accession record. Yet, that fails with a "undefined method `add_dynamaterial_type_list' for #<Accession:0x11cb666a>" error. So far, I have tried whatever I could think up, without success. I have added comments detailing options I've tried, and their effects.

I hope I'm overseeing something obvious and would very much appreciate any help, on- or off-list. If I can get it working properly, I will follow up here.

Many thanks in advance for any hints,

Ron

Joshua D. Shaw

unread,
Nov 25, 2025, 6:18:41 PM (7 days ago) Nov 25
to Archivesspac...@lyrasislists.org, Ron Van den Branden
Hey Ron

I think you're looking for a multiselect option - that stores the selected options as an array?  In that case, I think I might skip defining the enum outside of the core AS methods. 

Maybe something like this: https://github.com/dartmouth-dltg/aspace_content_warnings/blob/main/migrations/001_add_content_warnings_module.rb where you can define the subrecord table and populate the default enum values directly. 

For the schema and migration, I'd probably define a single column on the dynamaterial_type_list to hold an array of the material types. Each save would update that array with the latest values of material types.

The trickiest part will be storing and reading the array, but some custom update_from_json and create_from_json methods like you've got (maybe fiddled a bit) should do the trick on the backend - perhaps with a sequel_to_jsonmodel method to unwind for the frontend. Something like:  https://github.com/dartmouth-dltg/local_contexts_projects/blob/main/backend/model/local_contexts_project.rb

For the frontend, you'll have to do a similar process of taking an array and creating a multiselect and then packaging up the selected options into an array.

If I've understood what you're going for....?  I'd probably try and avoid the complication of the multiple related tables that you've got now and just have that one table for the subrecord which stores the enum values as an array.

jds


From: 'Ron Van den Branden' via Archivesspace_Users_Group <Archivesspac...@lyrasislists.org>
Sent: Tuesday, November 25, 2025 3:37 PM
To: archivesspac...@lyrasislists.org <archivesspac...@lyrasislists.org>
Subject: [ArchivesSpace Users Group] help needed: plugin creating a multi-select dropdown
 
--
You received this message because you are subscribed to the Google Groups "Archivesspace_Users_Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to Archivesspace_User...@lyrasislists.org.
To view this discussion visit https://groups.google.com/a/lyrasislists.org/d/msgid/Archivesspace_Users_Group/DU0PR02MB97287110E9778EFE311A8C9288D1A%40DU0PR02MB9728.eurprd02.prod.outlook.com.

Joshua D. Shaw

unread,
Nov 25, 2025, 6:25:57 PM (7 days ago) Nov 25
to archivesspac...@lyrasislists.org, Ron Van den Branden
PS. Doing it the way I've outlined would also mean adding some error handling to deal with enum values that may have been stored in the subrecord but subsequently deleted from the enum values. Validate steps on the backend and frontend should be pretty doable.

jds


From: archivesspac...@lyrasislists.org <archivesspac...@lyrasislists.org> on behalf of Joshua D. Shaw <Joshua...@dartmouth.edu>
Sent: Tuesday, November 25, 2025 6:18 PM
To: archivesspac...@lyrasislists.org <Archivesspac...@lyrasislists.org>; Ron Van den Branden <ron.vand...@antwerpen.be>
Subject: [ArchivesSpace Users Group] Re: help needed: plugin creating a multi-select dropdown
 

Ron Van den Branden

unread,
Nov 26, 2025, 5:49:53 AM (7 days ago) Nov 26
to Joshua D. Shaw, archivesspac...@lyrasislists.org
Thanks, Joshua,

My main goal is to have a multi-select dropdown in the SUI. Ideally, it would be facet-able, so accessions could be filtered on their material types. Would that be possible if the values are stored as an array in a single column in the db?

I did try an alternative, flatter approach, though (in the 'simpler structure' branch of my Git repo), that just stores the material types in a single table, where each row contains a link to the accession record, and one single material type. But so far, I didn't manage to get past a (gentler)  "Must be a (schema) (you provided a Array)" warning when trying to store the values. But if that is a better approach (the simpler, the merrier), I'll look at that again, and compare with your (interesting!) plugin example.

Best,

Ron

Van: Joshua D. Shaw <Joshua...@dartmouth.edu>
Verzonden: woensdag 26 november 2025 00:25
Aan: archivesspac...@lyrasislists.org <archivesspac...@lyrasislists.org>; Ron Van den Branden <ron.vand...@antwerpen.be>
Onderwerp: Re: help needed: plugin creating a multi-select dropdown
 

WAARSCHUWING: DIT IS EEN EXTERNE MAIL

Deze mail komt van buiten onze organisatie. Kijk eerst of je het mailadres en de afzender herkent en/of vertrouwt. Doe dat voor je bijlagen opent of links aanklikt. Zo houden we onze organisatie veiliger voor phishing. 

Joshua D. Shaw

unread,
Nov 26, 2025, 7:27:25 AM (7 days ago) Nov 26
to archivesspac...@lyrasislists.org
Hey Ron

I think you could create the indexer fields by iterating over the stored values and adding the booleans 'dynamically'. Kinda like so

if doc['primary_type'] == 'accession'
  if record['record']['dynamaterial_types']
    record['record']['dynamaterial_types'].each do |dmt|
      doc["#{dmt}_u_ubool"] = true
    end
  end
end 

For the db CRUD in the dynamaterial_types model, you'd probably want something along the lines of:

def valid_dmts
  # return valid enum values for dyn materials
  # something like 
  dyn_mat_enum_id = Enumerations.filter(:name => dyn_mat_enum_name).get(:id)
  allowed = []
  EnumerationValues.filter(:enumeration_id => dyn_mat_enum_id).each do |dmt|
    allowed << dmt[:value]
  end

  allowed
end 

def validate_dmt_list(dmts)
  allowed = valid_dmts
  dmts.keep_if { |element| allowed.include?(element) }

  dmts
end

def self.create_from_json(json, opts = {})
  allowed_dmts = validate_dmt_list(json.dmt_list)
  super(json, opts.merge('dmt_list' => JSON(json.allowed_dmts || [])))
end

def update_from_json(json, opts = {}, apply_nested_records = true)
  allowed_dmts = validate_dmt_list(json.dmt_list)
  super(json, opts.merge('dmt_list' => JSON(json.allowed_dmts || [])))
end

def self.sequel_to_jsonmodel(objs, opts = {})
  jsons = super
  jsons.zip(objs).each do |json, obj|
    json['dmt_list'] = ASUtils.json_parse(obj.dmt_list)
  end
end

Bit handwavy, but I think that's the way I'd approach this at first.

jds

From: Ron Van den Branden <ron.vand...@antwerpen.be>
Sent: Wednesday, November 26, 2025 5:49 AM
To: Joshua D. Shaw <Joshua...@dartmouth.edu>; archivesspac...@lyrasislists.org <archivesspac...@lyrasislists.org>
Subject: Re: help needed: plugin creating a multi-select dropdown
 
Reply all
Reply to author
Forward
0 new messages