Skip to content

Commit

Permalink
Adds service for duplicating a work version.
Browse files Browse the repository at this point in the history
refs #2674
  • Loading branch information
justinlittman committed Dec 13, 2022
1 parent 1d7b6d3 commit 2393599
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
66 changes: 66 additions & 0 deletions app/services/new_version_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# frozen_string_literal: true

# Duplicates a version, creating new related objects rather than point at objects for a past version.
# This is like NewVersionParameter, but it works on objects instead of parameters.
class NewVersionService
# @param [WorkVersion] old_version
# @return [WorkVersion] the new version
def self.dup(old_version, increment_version: false, save: false, version_description: nil, state: nil)
new(old_version).dup(increment_version:, save:, version_description:, state:)
end

def initialize(old_version)
@old_version = old_version
# Dup does not copy associations.
@new_version = old_version.dup
end

def dup(increment_version: false, save: false, version_description: nil, state: nil)
dup_attached_files
associations_to_filter.each do |relation|
dup_relation(relation)
end

new_version.version = old_version.version + 1 if increment_version
new_version.version_description = version_description if version_description
new_version.state = state if state
perform_save if save

new_version
end

private

attr_reader :old_version, :new_version

def dup_attached_files
old_version.attached_files.each do |existing_attached_file|
new_version.attached_files << dup_attached_file(existing_attached_file)
end
end

def dup_attached_file(existing_attached_file)
new_attached_file = existing_attached_file.dup
new_attached_file.file.attach(existing_attached_file.file.blob.signed_id)
new_attached_file
end

def dup_relation(relation)
old_version.public_send(relation).each do |existing_relation|
new_relation = existing_relation.dup
new_version.public_send(relation) << new_relation
end
end

def associations_to_filter
WorkVersion.aggregate_associations - [:attached_files]
end

def perform_save
work = old_version.work
work.transaction do
new_version.save!
work.update!(head_id: new_version.id)
end
end
end
36 changes: 36 additions & 0 deletions spec/services/new_version_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe NewVersionService do
let(:new_version) do
described_class.dup(existing_version, increment_version: true, save: true, version_description: 'A dup',
state: :version_draft)
end

let(:existing_version) { create(:work_version_with_work_and_collection) }

let(:attached_file) { create(:attached_file, :with_file) }

before do
existing_version.update(attached_files: [attached_file])
end

it 'duplicates the version' do
expect(new_version).to be_a WorkVersion
expect(new_version.persisted?).to be true
expect(new_version.version).to be 2
expect(new_version.version_description).to eq 'A dup'
expect(new_version.version_draft?).to be true
existing_version.reload
expect(new_version.title).to eq existing_version.title
expect(new_version.work).to eq existing_version.work
expect(existing_version.work.head).to eq new_version
expect(new_version.attached_files.count).to eq existing_version.attached_files.count
expect(new_version.attached_files.first.label).to eq existing_version.attached_files.first.label
expect(new_version.attached_files.first.blob.checksum).to eq existing_version.attached_files.first.blob.checksum
expect(new_version.keywords.count).to eq existing_version.keywords.count
expect(new_version.keywords.first.label).to eq existing_version.keywords.first.label
expect(new_version.authors.count).to eq existing_version.authors.count
end
end

0 comments on commit 2393599

Please sign in to comment.