Skip to content
This repository has been archived by the owner on Jan 5, 2021. It is now read-only.

Commit

Permalink
Merge pull request #859 from psu-libraries/i#649-file-downloads
Browse files Browse the repository at this point in the history
DownloadsController for files
  • Loading branch information
carolyncole committed Mar 13, 2019
2 parents c6231ce + dcdf246 commit c1b8ab1
Show file tree
Hide file tree
Showing 11 changed files with 341 additions and 10 deletions.
12 changes: 4 additions & 8 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2019-03-06 09:31:06 -0500 using RuboCop version 0.52.1.
# on 2019-03-11 16:18:10 -0400 using RuboCop version 0.52.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand All @@ -9,14 +9,9 @@
# Offense count: 3
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/BlockLength:
Max: 41
Max: 42

# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 102

# Offense count: 62
# Offense count: 63
RSpec/ExpectActual:
Exclude:
- 'spec/routing/**/*'
Expand All @@ -28,6 +23,7 @@ RSpec/ExpectActual:
- 'spec/cho/collection/curated_collections/curated_collections_routing_spec.rb'
- 'spec/cho/collection/library_collections/library_collections_routing_spec.rb'
- 'spec/cho/data_dictionary/routing_spec.rb'
- 'spec/cho/repository/downloads_routing_spec.rb'
- 'spec/cho/work/file_set/routing_spec.rb'
- 'spec/cho/work/import/routing_spec.rb'
- 'spec/cho/work/submissions/routing_spec.rb'
Expand Down
53 changes: 53 additions & 0 deletions app/cho/repository/download.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

module Repository
class Download
attr_reader :id, :use

def initialize(id:, use: nil)
@id = id
@use = use
end

def available?
file.present? && Pathname.new(file.path).exist?
end

def file
@file ||= begin
return if file_set.nil?
select_file
end
end

delegate :path, to: :file

private

def select_file
case use
when 'PreservationMasterFile'
preservation_file
when 'ServiceFile'
file_set.service
when 'AccessFile'
file_set.access
else
default_file
end
end

def preservation_file
file_set.preservation_redacted || file_set.preservation
end

def default_file
file_set.service || preservation_file
end

def file_set
@file_set ||= Valkyrie.config.metadata_adapter.query_service.find_by(id: Valkyrie::ID.new(id))
rescue Valkyrie::Persistence::ObjectNotFoundError
end
end
end
19 changes: 19 additions & 0 deletions app/cho/repository/downloads_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module Repository
class DownloadsController < ApplicationController
def download
if resource.available?
send_file(resource.path)
else
render file: 'public/404.html', status: 404, layout: false
end
end

private

def resource
@resource ||= Download.new(id: params.fetch(:id), use: params.fetch(:use_type, nil))
end
end
end
5 changes: 4 additions & 1 deletion app/views/catalog/_file_sets.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

<ul>
<%- file_sets.each do |file_set| %>
<li><%= link_to file_set.title.first, solr_document_path(file_set) %></li>
<li>
<%= link_to file_set.title.first, solr_document_path(file_set) %>
<%= link_to 'Download', download_path(file_set), data: { turbolinks: false } %>
</li>
<%- end %>
</ul>
7 changes: 6 additions & 1 deletion app/views/catalog/_show_work_fileset.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
<h2>Files</h2>
<ul>
<%- @document.files.each do |file| %>
<li><%= file.original_filename %></li>
<li>
<%= file.original_filename %>
<%= link_to 'Download',
download_path(@document.id, use_type: file.use.first.fragment),
data: { turbolinks: false } %>
</li>
<%- end %>
</ul>
<% end %>
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
post '/csv/agents/validate', to: 'agent/import/csv#validate'
post '/csv/agents/import', to: 'agent/import/csv#import'

get '/downloads/:id', to: 'repository/downloads#download', as: 'download'

resource :select, only: [:index], as: 'select', path: 'select', controller: 'batch/select' do
concerns :searchable
end
Expand Down
41 changes: 41 additions & 0 deletions spec/cho/repository/download_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Repository::Download, type: :model do
describe '#available?' do
subject { described_class.new(id: file_set.id) }

context 'when the file set has a file that is present on the system' do
let(:file_set) { create(:file_set, :with_member_file) }

it { is_expected.to be_available }
end

context 'when the file in the file set is missing from the system' do
let(:file_set) { create(:file_set, :with_missing_file) }

it { is_expected.not_to be_available }
end

context 'when the file does not have a file' do
let(:file_set) { create(:file_set) }

it { is_expected.not_to be_available }
end
end

describe '#path' do
subject { described_class.new(id: 'id') }

it { is_expected.to delegate_method(:path).to(:file) }
end

describe '#file' do
subject { described_class.new(id: file_set.id) }

let(:file_set) { create(:file_set, :with_member_file) }

its(:file) { is_expected.to be_kind_of(Work::File) }
end
end
112 changes: 112 additions & 0 deletions spec/cho/repository/downloads_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Repository::DownloadsController, type: :controller do
describe 'GET #download' do
context 'when not requesting a specific use type with a preservation file present' do
let(:file_set) { create(:file_set, :with_preservation_file) }

specify do
get :download, params: { id: file_set.id }
expect(response).to be_success
expect(response.body).to eq('Hello World!')
end
end

context 'when not requesting a specific use type with a redacted preservation file present' do
let(:file_set) { create(:file_set, :with_redacted_preservation_file) }

specify do
get :download, params: { id: file_set.id }
expect(response).to be_success
expect(response.body).to eq('Hello World!')
end
end

context 'when not requesting a specific use type with a service file present' do
let(:file_set) { create(:file_set, :with_service_file) }

specify do
get :download, params: { id: file_set.id }
expect(response).to be_success
expect(response.body).to eq('Hello World!')
end
end

context 'when requesting the preservation file when a redacted one is present' do
let(:file_set) { create(:file_set, :with_redacted_preservation_file) }

specify do
get :download, params: { id: file_set.id, use_type: 'PreservationMasterFile' }
expect(response).to be_success
expect(response.body).to eq('Hello World!')
end
end

context 'when requesting the preservation file' do
let(:file_set) { create(:file_set, :with_preservation_file) }

specify do
get :download, params: { id: file_set.id, use_type: 'PreservationMasterFile' }
expect(response).to be_success
expect(response.body).to eq('Hello World!')
end
end

context 'when requesting the access file' do
let(:file_set) { create(:file_set, :with_access_file) }

specify do
get :download, params: { id: file_set.id, use_type: 'AccessFile' }
expect(response).to be_success
expect(response.body).to eq('Hello World!')
end
end

context 'when requesting the service file' do
let(:file_set) { create(:file_set, :with_service_file) }

specify do
get :download, params: { id: file_set.id, use_type: 'ServiceFile' }
expect(response).to be_success
expect(response.body).to eq('Hello World!')
end
end

context 'with an unsupported use type' do
let(:file_set) { create(:file_set, :with_service_file) }

specify do
get :download, params: { id: file_set.id, use_type: :bogus }
expect(response).to be_success
expect(response.body).to eq('Hello World!')
end
end

context 'with no files in the file set' do
let(:file_set) { create(:file_set) }

specify do
get :download, params: { id: file_set.id }
expect(response).to be_not_found
end
end

context 'when the file set does not exist' do
specify do
get :download, params: { id: 'missing-id' }
expect(response).to be_not_found
end
end

context 'when the file does not exist' do
let(:file_set) { create(:file_set, :with_missing_file) }

specify do
get :download, params: { id: file_set.id }
expect(response).to be_not_found
end
end
end
end
11 changes: 11 additions & 0 deletions spec/cho/repository/downloads_routing_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Repository::DownloadsController, type: :routing do
describe 'routing' do
it 'has a route to #download' do
expect(get: '/downloads/1').to route_to('repository/downloads#download', id: '1')
end
end
end
71 changes: 71 additions & 0 deletions spec/factories/file_sets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,75 @@
fileset
end
end

trait :with_preservation_file do
to_create do |resource, attributes|
result = FileFactory.new.hello_world

resource.member_ids = [result.success.id]
fileset = Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: resource)
work = attributes.work
work ||= FactoryBot.build(:work_submission)
work.member_ids << fileset.id
Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: work)
fileset
end
end

trait :with_missing_file do
to_create do |resource, attributes|
result = FileFactory.new.hello_world
FileUtils.rm_f(result.success.resource.path)

resource.member_ids = [result.success.id]
fileset = Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: resource)
work = attributes.work
work ||= FactoryBot.build(:work_submission)
work.member_ids << fileset.id
Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: work)
fileset
end
end

trait :with_redacted_preservation_file do
to_create do |resource, attributes|
result = FileFactory.new(use: Vocab::FileUse.RedactedPreservationMasterFile).hello_world

resource.member_ids = [result.success.id]
fileset = Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: resource)
work = attributes.work
work ||= FactoryBot.build(:work_submission)
work.member_ids << fileset.id
Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: work)
fileset
end
end

trait :with_service_file do
to_create do |resource, attributes|
result = FileFactory.new(use: Valkyrie::Vocab::PCDMUse.ServiceFile).hello_world

resource.member_ids = [result.success.id]
fileset = Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: resource)
work = attributes.work
work ||= FactoryBot.build(:work_submission)
work.member_ids << fileset.id
Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: work)
fileset
end
end

trait :with_access_file do
to_create do |resource, attributes|
result = FileFactory.new(use: Vocab::FileUse.AccessFile).hello_world

resource.member_ids = [result.success.id]
fileset = Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: resource)
work = attributes.work
work ||= FactoryBot.build(:work_submission)
work.member_ids << fileset.id
Valkyrie::MetadataAdapter.find(:indexing_persister).persister.save(resource: work)
fileset
end
end
end
Loading

0 comments on commit c1b8ab1

Please sign in to comment.