Skip to content

Commit

Permalink
🧹 expands the ability to upload remote_files for valkyrie (#967)
Browse files Browse the repository at this point in the history
* 🧹 expands the ability to upload remote_files for valkyrie resources

Previously this code strictly downloaded from s3 buckets. This was limiting, and expands the ability to import remote files without s3.

* Adds ability to set filename

* remove comment

* adds ability to import thumbnail_url

* Completes import with remote files

- Provides a valkyrized way to import from a remote url.
- Supports additional file set arguments if present.
- Adds filename to Hyrax's UploadedFile table, to allow overriding of
carrierwave's default file name behavior.

refs
- scientist-softserv/adventist_knapsack#708
- scientist-softserv/adventist_knapsack#723

* 💄 fix rubocop errors

* 🧹 fix for failing migration

error: NoMethodError: undefined method `column_exists' for #<AddFileNameToUploadedFiles:0x000055d8c48ea0b0 @name="AddFileNameToUploadedFiles", @Version=20240806161142, @connection=nil>

---------

Co-authored-by: LaRita Robinson <larita@scientist.com>
  • Loading branch information
ShanaLMoore and laritakr authored Aug 14, 2024
1 parent fe15dde commit 176b11a
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 3 deletions.
70 changes: 67 additions & 3 deletions app/factories/bulkrax/valkyrie_object_factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,16 +252,40 @@ def create_work(attrs)
# NOTE: We do not add relationships here; that is part of the create
# relationships job.
perform_transaction_for(object: object, attrs: attrs) do
uploaded_files = uploaded_files_from(attrs)
file_set_params = file_set_params_for(uploaded_files, combined_files_with(remote_files: attrs["remote_files"]))
transactions["change_set.create_work"]
.with_step_args(
'work_resource.add_file_sets' => { uploaded_files: uploaded_files_from(attrs) },
'work_resource.add_file_sets' => { uploaded_files: uploaded_files, file_set_params: file_set_params },
"change_set.set_user_as_depositor" => { user: @user },
"work_resource.change_depositor" => { user: @user },
'work_resource.save_acl' => { permissions_params: [attrs['visibility'] || 'open'].compact }
)
end
end

def combined_files_with(remote_files:)
thumbnail_url = self.attributes['thumbnail_url']
@combined_files ||= (thumbnail_url.present? ? remote_files + [thumbnail_url] : remote_files)
end

def file_set_params_for(uploaded_files, combined_files)
# handling remote files requires a filename to avoid the default carrierwave file name assignment.
# Here we tag along only the keys that are not 'url' or 'file_name' as file_set attributes.
# To have the additional attributes appear on the file_set, they must be:
# - included in the file_set_metadata.yaml
# - overriden in file_set_args from Hyrax::WorkUploadsHandler
additional_attributes = combined_files.map do |hash|
hash.reject { |key, _| key == 'url' || key == 'file_name' }
end

file_attrs = []
uploaded_files.each_with_index do |f, index|
file_attrs << ({ uploaded_file_id: f["id"].to_s, filename: combined_files[index]["file_name"] }).merge(additional_attributes[index])
end
file_attrs.compact.uniq
end

def create_collection(attrs)
# TODO: Handle Collection Type
#
Expand Down Expand Up @@ -329,9 +353,11 @@ def permitted_attributes

def update_work(attrs)
perform_transaction_for(object: object, attrs: attrs) do
uploaded_files = uploaded_files_from(attrs)
file_set_params = file_set_params_for(uploaded_files, combined_files_with(remote_files: attrs["remote_files"]))
transactions["change_set.update_work"]
.with_step_args(
'work_resource.add_file_sets' => { uploaded_files: uploaded_files_from(attrs) },
'work_resource.add_file_sets' => { uploaded_files: uploaded_files, file_set_params: file_set_params },
'work_resource.save_acl' => { permissions_params: [attrs.try('visibility') || 'open'].compact }
)
end
Expand All @@ -350,7 +376,10 @@ def update_file_set(attrs)
end

def uploaded_files_from(attrs)
uploaded_local_files(uploaded_files: attrs[:uploaded_files]) + uploaded_s3_files(remote_files: attrs[:remote_files])
uploaded_local_files(uploaded_files: attrs[:uploaded_files]) +
# TODO: disabled until we get s3 details
# uploaded_s3_files(remote_files: attrs[:remote_files]) +
uploaded_remote_files(remote_files: attrs[:remote_files])
end

def uploaded_local_files(uploaded_files: [])
Expand All @@ -371,6 +400,41 @@ def uploaded_s3_files(remote_files: {})
end.compact
end

def uploaded_remote_files(remote_files: {})
combined_files_with(remote_files: remote_files).map do |r|
file_path = download_file(r["url"])
next unless file_path

create_uploaded_file(file_path, r["file_name"])
end.compact
end

def download_file(url)
require 'open-uri'
require 'tempfile'

begin
file = Tempfile.new
file.binmode
file.write(URI.open(url).read)
file.rewind
file.path
rescue => e
Rails.logger.debug "Failed to download file from #{url}: #{e.message}"
nil
end
end

def create_uploaded_file(file_path, file_name)
file = File.open(file_path)
uploaded_file = Hyrax::UploadedFile.create(file: file, user: @user, filename: file_name)
file.close
uploaded_file
rescue => e
Rails.logger.debug "Failed to create Hyrax::UploadedFile for #{file_name}: #{e.message}"
nil
end

# @Override Destroy existing files with Hyrax::Transactions
def destroy_existing_files
existing_files = Hyrax.custom_queries.find_child_file_sets(resource: object)
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20240806161142_add_file_name_to_uploaded_files.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddFileNameToUploadedFiles < ActiveRecord::Migration[6.1]
def change
add_column :uploaded_files, :filename, :string unless column_exists?(:uploaded_files, :filename)
end
end

0 comments on commit 176b11a

Please sign in to comment.