Clone file version history when making new protocol draft [SCI-11230]

This commit is contained in:
Martin Artnik 2024-10-30 15:23:48 +01:00
parent 89bc4102ee
commit d3292f6c4a
3 changed files with 49 additions and 35 deletions

View file

@ -146,49 +146,61 @@ class Asset < ApplicationRecord
file&.blob&.content_type
end
def duplicate(new_name: nil)
def duplicate(new_name: nil, include_file_versions: false)
new_asset = dup
file.filename = new_name if new_name
return unless new_asset.save
duplicate_file(new_asset, new_name: new_name)
duplicate_file(new_asset, new_name: new_name, include_file_versions: include_file_versions)
new_asset
end
def duplicate_file(to_asset, new_name: nil)
def duplicate_blob(blob, attach_method, metadata: nil)
new_blob = nil
blob.open do |tmp_file|
new_blob = ActiveStorage::Blob.create_and_upload!(
io: tmp_file,
filename: blob.filename,
metadata: metadata || blob.metadata
)
attach_method.call(new_blob)
end
new_blob
end
def duplicate_file_versions(to_asset)
previous_files.map(&:blob).sort_by(&:created_at).each do |blob|
duplicate_blob(blob, to_asset.previous_files.method(:attach)) # .update_column(:created_at, blob.created_at)
end
end
def duplicate_file(to_asset, new_name: nil, include_file_versions: false)
return unless file.attached?
raise ArgumentError, 'Destination asset should be persisted first!' unless to_asset.persisted?
file.blob.open do |tmp_file|
metadata = blob.metadata.dup
metadata = file.blob.metadata.dup
# set new name in metadata for OVE and MarvinJS files
if new_name && file.blob.metadata['asset_type'].in?(%w(gene_sequence marvinjs))
new_metadata_name = File.basename(new_name, File.extname(new_name))
metadata['name'] = new_metadata_name
end
to_blob = ActiveStorage::Blob.create_and_upload!(
io: tmp_file,
filename: blob.filename,
metadata: metadata
)
to_asset.attach_file_version(to_blob)
# set new name in metadata for OVE and MarvinJS files
if new_name && file.blob.metadata['asset_type'].in?(%w(gene_sequence marvinjs))
new_metadata_name = File.basename(new_name, File.extname(new_name))
metadata['name'] = new_metadata_name
end
if preview_image.attached?
preview_image.blob.open do |tmp_preview_image|
to_blob = ActiveStorage::Blob.create_and_upload!(
io: tmp_preview_image,
filename: blob.filename,
metadata: blob.metadata
)
to_asset.attach_preview_image_version(to_blob)
end
unless include_file_versions
metadata.delete('version')
metadata.delete('restored_from_version')
end
duplicate_file_versions(to_asset) if include_file_versions
duplicate_blob(blob, to_asset.method(:attach_file_version), metadata: metadata)
duplicate_blob(preview_image.blob, to_asset.method(:attach_preview_image_version)) if preview_image.attached?
to_asset.post_process_file
end

View file

@ -351,7 +351,9 @@ class Protocol < ApplicationRecord
end
# Deep-clone given array of assets
def self.deep_clone_assets(assets_to_clone)
# There is an issue with Delayed Job delayed methods, ruby 3, and keyword arguments (https://github.com/collectiveidea/delayed_job/issues/1134)
# so we're forced to use a normal argument with default value.
def self.deep_clone_assets(assets_to_clone, include_file_versions = false)
ActiveRecord::Base.no_touching do
assets_to_clone.each do |src_id, dest_id|
src = Asset.find_by(id: src_id)
@ -360,12 +362,12 @@ class Protocol < ApplicationRecord
next unless src.present? && dest.present?
# Clone file
src.duplicate_file(dest)
src.duplicate_file(dest, include_file_versions: include_file_versions)
end
end
end
def self.clone_contents(src, dest, current_user, clone_keywords, only_contents = false)
def self.clone_contents(src, dest, current_user, clone_keywords, only_contents: false, include_file_versions: false)
dest.update(description: src.description, name: src.name) unless only_contents
src.clone_tinymce_assets(dest, dest.team)
@ -382,7 +384,7 @@ class Protocol < ApplicationRecord
# Copy steps
src.steps.each do |step|
step.duplicate(dest, current_user, step_position: step.position)
step.duplicate(dest, current_user, step_position: step.position, include_file_versions: include_file_versions)
end
end
@ -615,7 +617,7 @@ class Protocol < ApplicationRecord
return draft if draft.invalid?
ActiveRecord::Base.no_touching do
draft = deep_clone(draft, current_user)
draft = deep_clone(draft, current_user, include_file_versions: true)
end
parent_protocol.user_assignments.each do |parent_user_assignment|
@ -760,7 +762,7 @@ class Protocol < ApplicationRecord
end
end
def deep_clone(clone, current_user)
def deep_clone(clone, current_user, include_file_versions: false)
# Save cloned protocol first
success = clone.save
@ -772,7 +774,7 @@ class Protocol < ApplicationRecord
raise ActiveRecord::RecordNotSaved unless success
Protocol.clone_contents(self, clone, current_user, true, true)
Protocol.clone_contents(self, clone, current_user, true, only_contents: true, include_file_versions: include_file_versions)
clone.reload
clone

View file

@ -117,7 +117,7 @@ class Step < ApplicationRecord
step_texts.order(created_at: :asc).first
end
def duplicate(protocol, user, step_position: nil, step_name: nil)
def duplicate(protocol, user, step_position: nil, step_name: nil, include_file_versions: false)
ActiveRecord::Base.transaction do
assets_to_clone = []
@ -153,7 +153,7 @@ class Step < ApplicationRecord
end
# Call clone helper
Protocol.delay(queue: :assets).deep_clone_assets(assets_to_clone)
Protocol.delay(queue: :assets).deep_clone_assets(assets_to_clone, include_file_versions)
new_step
end