diff --git a/app/jobs/migrate_resources_job.rb b/app/jobs/migrate_resources_job.rb new file mode 100644 index 0000000000..128f757793 --- /dev/null +++ b/app/jobs/migrate_resources_job.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# migrates models from AF to valkyrie +class MigrateResourcesJob < ApplicationJob + attr_accessor :errors + # input [Array>>String] Array of ActiveFedora model names to migrate to valkyrie objects + # defaults to AdminSet & Collection models if empty + def perform(models: ['AdminSet', 'Collection'], ids: []) + errors = [] + if ids.blank? + models.each do |model| + model.constantize.find_each do |item| + resource = Hyrax.query_service.find_by(id: item.id) + result = MigrateResourceService.new(resource: resource).call + errors << result unless result.success? + end + end + else + ids.each do |id| + resource = Hyrax.query_service.find_by(id: id) + next unless resource.wings? # this resource has already been converted + result = MigrateResourceService.new(resource: resource).call + errors << result unless result.success? + end + end + raise errors.inspect if errors.present? + end +end diff --git a/app/models/hyrax/resource.rb b/app/models/hyrax/resource.rb index a0499e96f2..766c5091d7 100644 --- a/app/models/hyrax/resource.rb +++ b/app/models/hyrax/resource.rb @@ -149,6 +149,11 @@ def work? self.class.work? end + # Its nice to know if a record is still in AF or not + def wings? + self.respond_to?(:head) && self.respond_to?(:tail) + end + def ==(other) attributes.except(:created_at, :updated_at) == other.attributes.except(:created_at, :updated_at) if other.respond_to?(:attributes) end diff --git a/app/services/migrate_resource_service.rb b/app/services/migrate_resource_service.rb new file mode 100644 index 0000000000..a8d2b2b41f --- /dev/null +++ b/app/services/migrate_resource_service.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +# migrates models from AF to valkyrie +class MigrateResourceService + attr_accessor :resource + def initialize(resource:) + @resource = resource + end + + def model + @model || Wings::ModelRegistry.lookup(resource.class).to_s + end + + def call + prep_resource + Hyrax::Transactions::Container[model_events(model)] + .with_step_args(**model_steps(model)).call(resource_form) + end + + def prep_resource + case model + when 'FileSet' + resource.creator << ::User.batch_user.email if resource.creator.blank? + end + end + + def resource_form + @resource_form ||= Hyrax::Forms::ResourceForm.for(resource: resource) + end + + def model_events(model) + { + 'AdminSet' => 'admin_set_resource.update', + 'Collection' => 'change_set.update_collection', + 'FileSet' => 'change_set.update_file_set' + }[model] || 'change_set.update_work' + end + + def model_steps(model) + { + 'AdminSet' => {}, + 'Collection' => { + 'collection_resource.save_collection_banner' => { banner_unchanged_indicator: true }, + 'collection_resource.save_collection_logo' => { logo_unchanged_indicator: true } + }, + 'FileSet' => { + 'file_set.save_acl' => {} + } + }[model] || { + 'work_resource.add_file_sets' => { uploaded_files: [], file_set_params: [] }, + 'work_resource.update_work_members' => { work_members_attributes: [] }, + 'work_resource.save_acl' => { permissions_params: [] } + } + end +end diff --git a/lib/freyja/persister.rb b/lib/freyja/persister.rb index 0c7052a347..a4122e7ac2 100644 --- a/lib/freyja/persister.rb +++ b/lib/freyja/persister.rb @@ -32,8 +32,9 @@ def save(resource:, external_resource: false, perform_af_validation: false) def convert_and_migrate_resource(orm_object) new_resource = resource_factory.to_resource(object: orm_object) - if Hyrax.config.valkyrie_transition? && new_resource.is_a?(Hyrax::FileSet) && new_resource.file_ids.size == 1 && new_resource.file_ids.first.id.to_s.match('/files/') - MigrateFilesToValkyrieJob.perform_later(new_resource) + if Hyrax.config.valkyrie_transition? + MigrateFilesToValkyrieJob.perform_later(new_resource) if new_resource.is_a?(Hyrax::FileSet) && new_resource.file_ids.size == 1 && new_resource.file_ids.first.id.to_s.match('/files/') + MigrateResourcesJob.perform_later(ids: new_resource.member_ids) if new_resource.is_a?(Hyrax::Work) end new_resource end diff --git a/spec/jobs/migrate_resources_job_spec.rb b/spec/jobs/migrate_resources_job_spec.rb new file mode 100644 index 0000000000..4eb7102f3d --- /dev/null +++ b/spec/jobs/migrate_resources_job_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'freyja/persister' +RSpec.describe MigrateResourcesJob, clean: true do + before do + ActiveJob::Base.queue_adapter = :test + FactoryBot.create(:group, name: "public") + end + + after do + clear_enqueued_jobs + end + + let(:account) { create(:account_with_public_schema) } + let(:af_file_set) { create(:file_set, title: ['TestFS']) } + + let!(:af_admin_set) do + as = AdminSet.new(title: ['AF Admin Set']) + as.save + AdminSet.find(as.id) + end + + describe '#perform' do + it "migrates admin sets to valkyrie", active_fedora_to_valkyrie: true do + expect(Valkyrie::Persistence::Postgres::ORM::Resource.find_by(id: af_admin_set.id.to_s)).to be_nil + + ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true + switch!(account) + MigrateResourcesJob.perform_now + + expect(Valkyrie::Persistence::Postgres::ORM::Resource.find_by(id: af_admin_set.id.to_s)).to be_present + end + + it "migrates a file set by its id", active_fedora_to_valkyrie: true do + expect(Valkyrie::Persistence::Postgres::ORM::Resource.find_by(id: af_file_set.id.to_s)).to be_nil + + ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true + switch!(account) + MigrateResourcesJob.perform_now(ids: [af_file_set.id]) + + expect(Valkyrie::Persistence::Postgres::ORM::Resource.find_by(id: af_file_set.id.to_s)).to be_present + end + end +end