Skip to content

Commit

Permalink
Add work to a collection.
Browse files Browse the repository at this point in the history
Fixes #1708
  • Loading branch information
jcoyne committed Apr 1, 2016
1 parent 53965fa commit aac3eb8
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 69 deletions.
47 changes: 47 additions & 0 deletions app/actors/sufia/create_with_collections_actor.rb
@@ -0,0 +1,47 @@
module Sufia
# Creates a work and attaches files to the work
class CreateWithCollectionsActor
attr_reader :work_actor, :collection_ids

def initialize(work_actor, collection_ids)
@work_actor = work_actor
@collection_ids = collection_ids
end

delegate :visibility_changed?, to: :work_actor

def create
validate_collections && work_actor.create && add_to_collections
end

def update
validate_collections && work_actor.update && add_to_collections
end

protected

# ensure that the collections we are given are owned by the depositor of the work
def validate_collections
expected_user_id = work_actor.user.id
uploaded_files.each do |file|
if file.user_id != expected_user_id
Rails.logger.error "User #{work_actor.user.user_key} attempted to ingest uploaded_file #{file.id}, but it belongs to a different user"
return false
end
end
true
end

# @return [TrueClass]
def attach_files
AddWorkToCollectionJob.perform_later(work_actor.curation_concern, uploaded_files)
true
end

# Fetch collections from Fedora
def collections
return [] unless collection_ids
@collections ||= Collection.find(collection_ids)
end
end
end
31 changes: 12 additions & 19 deletions app/actors/sufia/create_with_files_actor.rb
@@ -1,31 +1,24 @@
module Sufia
# Creates a work and attaches files to the work
class CreateWithFilesActor
attr_reader :work_actor, :uploaded_file_ids

def initialize(work_actor, uploaded_file_ids)
@work_actor = work_actor
@uploaded_file_ids = uploaded_file_ids
end

delegate :visibility_changed?, to: :work_actor

def create
validate_files && work_actor.create && attach_files
class CreateWithFilesActor < CurationConcerns::AbstractActor
def create(attributes)
@uploaded_file_ids = attributes.delete(:uploaded_files)
validate_files && next_actor.create(attributes) && attach_files
end

def update
validate_files && work_actor.update && attach_files
def update(attributes)
@uploaded_file_ids = attributes.delete(:uploaded_files)
validate_files && next_actor.update(attributes) && attach_files
end

protected

# ensure that the files we are given are owned by the depositor of the work
def validate_files
expected_user_id = work_actor.user.id
expected_user_id = user.id
uploaded_files.each do |file|
if file.user_id != expected_user_id
Rails.logger.error "User #{work_actor.user.user_key} attempted to ingest uploaded_file #{file.id}, but it belongs to a different user"
Rails.logger.error "User #{user.user_key} attempted to ingest uploaded_file #{file.id}, but it belongs to a different user"
return false
end
end
Expand All @@ -34,14 +27,14 @@ def validate_files

# @return [TrueClass]
def attach_files
AttachFilesToWorkJob.perform_later(work_actor.curation_concern, uploaded_files)
AttachFilesToWorkJob.perform_later(curation_concern, uploaded_files)
true
end

# Fetch uploaded_files from the database
def uploaded_files
return [] unless uploaded_file_ids
@uploaded_files ||= UploadedFile.find(uploaded_file_ids)
return [] unless @uploaded_file_ids
@uploaded_files ||= UploadedFile.find(@uploaded_file_ids)
end
end
end
20 changes: 16 additions & 4 deletions app/controllers/concerns/sufia/works_controller_behavior.rb
Expand Up @@ -25,10 +25,22 @@ def edit
end

def actor
@actor ||= begin
inner_actor = CurationConcerns::CurationConcern.actor(curation_concern, current_user, attributes_for_actor)
Sufia::CreateWithFilesActor.new(inner_actor, params[:uploaded_files])
end
@actor ||= CurationConcerns::CurationConcern::ActorStack.new(
curation_concern,
current_user,
[CreateWithFilesActor,
CurationConcerns::AddToCollectionActor,
CurationConcerns::AssignRepresentativeActor,
CurationConcerns::AttachFilesActor,
CurationConcerns::ApplyOrderActor,
CurationConcerns::InterpretVisibilityActor,
CurationConcerns::CurationConcern.model_actor(curation_concern),
CurationConcerns::AssignIdentifierActor])
end

# Override the default behavior from curation_concerns in order to add uploaded_files to the parameters received by the actor.
def attributes_for_actor
super.merge(params.slice(:uploaded_files))
end

def after_create_response
Expand Down
18 changes: 16 additions & 2 deletions app/forms/sufia/forms/work_form.rb
Expand Up @@ -2,15 +2,29 @@ module Sufia::Forms
class WorkForm < CurationConcerns::Forms::WorkForm
delegate :depositor, :permissions, to: :model

self.terms += [:collection_ids]

def [](key)
return [] if key == :collection_ids
super
end

# Fields that are in rendered terms are automatically drawn on the page.
def rendered_terms
terms - [:files, :visibility_during_embargo, :embargo_release_date,
:visibility_after_embargo, :visibility_during_lease,
:lease_expiration_date, :visibility_after_lease, :visibility, :thumbnail_id, :representative_id, :ordered_member_ids]
:lease_expiration_date, :visibility_after_lease, :visibility,
:thumbnail_id, :representative_id, :ordered_member_ids,
:collection_ids]
end

def self.multiple?(term)
return true if term == :rights
return true if [:rights, :collection_ids].include? term
super
end

def self.build_permitted_params
super + [{ collection_ids: [] }]
end
end
end
6 changes: 3 additions & 3 deletions app/jobs/upload_set_update_job.rb
Expand Up @@ -58,10 +58,10 @@ def update_work(user, work, title, attributes)
end

work.title = title if title
work_actor(work, user, attributes).update
work_actor(work, user).update(attributes)
end

def work_actor(work, user, attributes)
CurationConcerns::GenericWorkActor.new(work, user, attributes)
def work_actor(work, user)
CurationConcerns::CurationConcern.actor(work, user)
end
end
4 changes: 3 additions & 1 deletion app/views/curation_concerns/base/_form.html.erb
Expand Up @@ -17,7 +17,9 @@
<div role="tabpanel" class="tab-pane" id="files">
<%= render 'form_files', f: f %>
</div>
<div role="tabpanel" class="tab-pane" id="relationships">...</div>
<div role="tabpanel" class="tab-pane" id="relationships">
<%= render 'form_relationships', f: f %>
</div>
<div role="tabpanel" class="tab-pane" id="share">...</div>
</div>
</div>
Expand Down
6 changes: 6 additions & 0 deletions app/views/curation_concerns/base/_form_relationships.html.erb
@@ -0,0 +1,6 @@
<h3>This Work in Collections</h3>
<div id="collection-widget">
<%= f.input :collection_ids, as: :select,
collection: available_collections(nil),
input_html: { class: 'form-control', multiple: true } %>
</div>
2 changes: 2 additions & 0 deletions config/locales/sufia.en.yml
Expand Up @@ -218,6 +218,8 @@ en:
related_url: "Related URL"
total_items: "Total Items"
size: "Size"
generic_work:
collection_ids: "Add as member of collection"

metadata_help:
file_set:
Expand Down
10 changes: 6 additions & 4 deletions lib/sufia/arkivo/actor.rb
Expand Up @@ -19,8 +19,9 @@ def initialize(user, item)
def create_work_from_item
upload_set = UploadSet.create
work = ::GenericWork.new
work_actor = CurationConcerns::GenericWorkActor.new(work, user, attributes.merge(arkivo_checksum: item['file']['md5']))
raise "Unable to create work. #{work.errors.messages}" unless work_actor.create
work_actor = CurationConcerns::CurationConcern.actor(work, user)
create_attrs = attributes.merge(arkivo_checksum: item['file']['md5'])
raise "Unable to create work. #{work.errors.messages}" unless work_actor.create(create_attrs)

file_set = ::FileSet.new

Expand All @@ -34,8 +35,9 @@ def create_work_from_item

def update_work_from_item(work)
reset_metadata(work)
work_actor = CurationConcerns::GenericWorkActor.new(work, user, attributes.merge(arkivo_checksum: item['file']['md5']))
work_actor.update
work_actor = CurationConcerns::CurationConcern.actor(work, user)
work_attributes = attributes.merge(arkivo_checksum: item['file']['md5'])
work_actor.update(work_attributes)
file_set = work.file_sets.first
file_actor = ::CurationConcerns::FileSetActor.new(file_set, user)
file_actor.update_content(file)
Expand Down
12 changes: 9 additions & 3 deletions spec/actors/create_with_files_actor_spec.rb
Expand Up @@ -4,29 +4,35 @@
let(:create_actor) { double('create actor', create: true,
curation_concern: work,
user: user) }
let(:actor) { described_class.new(create_actor, uploaded_file_ids) }
# let(:actor) { described_class.new(create_actor, uploaded_file_ids) }
let(:actor) do
CurationConcerns::CurationConcern::ActorStack.new(
work, user, [described_class])
end
let(:user) { create(:user) }
let(:uploaded_file1) { UploadedFile.create(user: user) }
let(:uploaded_file2) { UploadedFile.create(user: user) }
let(:work) { create(:generic_work, user: user) }
let(:uploaded_file_ids) { [uploaded_file1.id, uploaded_file2.id] }
let(:attributes) { { uploaded_files: uploaded_file_ids } }

before do
allow(CurationConcerns::RootActor).to receive(:new).and_return(create_actor)
allow(create_actor).to receive(:create).and_return(true)
end

context "when uploaded_file_ids belong to me" do
it "attaches files" do
expect(AttachFilesToWorkJob).to receive(:perform_later).with(GenericWork, [uploaded_file1, uploaded_file2])
expect(actor.create).to be true
expect(actor.create(attributes)).to be true
end
end

context "when uploaded_file_ids don't belong to me" do
let(:uploaded_file2) { UploadedFile.create }
it "doesn't attach files" do
expect(AttachFilesToWorkJob).not_to receive(:perform_later)
expect(actor.create).to be false
expect(actor.create(attributes)).to be false
end
end
end
7 changes: 4 additions & 3 deletions spec/controllers/generic_works_controller_spec.rb
Expand Up @@ -49,16 +49,17 @@
let(:actor) { double('An actor') }
let(:work) { create(:work) }
before do
allow(Sufia::CreateWithFilesActor).to receive(:new)
.with(CurationConcerns::GenericWorkActor, ['777', '888'])
allow(controller).to receive(:actor)
.and_return(actor)

# Stub out the creation of the work so we can redirect somewhere
allow(controller).to receive(:curation_concern).and_return(work)
end

it "attaches files" do
expect(actor).to receive(:create).and_return(true)
expect(actor).to receive(:create)
.with(hash_including(:uploaded_files))
.and_return(true)
post :create, generic_work: { title: ["First title"],
visibility: 'open' },
uploaded_files: ['777', '888']
Expand Down
28 changes: 0 additions & 28 deletions spec/form/work_form_spec.rb

This file was deleted.

1 change: 1 addition & 0 deletions spec/forms/upload_set_form_spec.rb
Expand Up @@ -45,6 +45,7 @@
:visibility_after_lease,
:visibility,
:ordered_member_ids,
:collection_ids,
:resource_type] }
end

Expand Down
53 changes: 51 additions & 2 deletions spec/forms/work_form_spec.rb
@@ -1,13 +1,62 @@
require 'spec_helper'

describe Sufia::Forms::WorkForm do
describe CurationConcerns::GenericWorkForm do
let(:form) { described_class.new(GenericWork.new, nil) }

describe "#rendered_terms" do
subject { form.rendered_terms }
it { is_expected.not_to include(:visibilty, :visibility_during_embargo,
:embargo_release_date, :visibility_after_embargo,
:visibility_during_lease, :lease_expiration_date,
:visibility_after_lease) }
:visibility_after_lease, :collection_ids) }
end

describe "#[]" do
subject { form[term] }
context "for collection_ids" do
let(:term) { :collection_ids }
it { is_expected.to eq [] }
end
end

describe '.model_attributes' do
let(:params) { ActionController::Parameters.new(
title: ['foo'],
description: [''],
visibility: 'open',
admin_set_id: '123',
representative_id: '456',
thumbnail_id: '789',
tag: ['derp'],
rights: ['http://creativecommons.org/licenses/by/3.0/us/'],
collection_ids: ['123456', 'abcdef']) }

subject { described_class.model_attributes(params) }

it 'permits parameters' do
expect(subject['title']).to eq ['foo']
expect(subject['description']).to be_empty
expect(subject['visibility']).to eq 'open'
expect(subject['rights']).to eq ['http://creativecommons.org/licenses/by/3.0/us/']
expect(subject['tag']).to eq ['derp']
expect(subject['collection_ids']).to eq ['123456', 'abcdef']
end

context '.model_attributes' do
let(:params) { ActionController::Parameters.new(
title: [''],
description: [''],
tag: [''],
rights: [''],
collection_ids: ['']) }

it 'removes blank parameters' do
expect(subject['title']).to be_empty
expect(subject['description']).to be_empty
expect(subject['rights']).to be_empty
expect(subject['tag']).to be_empty
expect(subject['collection_ids']).to be_empty
end
end
end
end
3 changes: 3 additions & 0 deletions spec/test_app_templates/Gemfile.extra
Expand Up @@ -4,3 +4,6 @@ group :development do
gem 'better_errors'
gem 'binding_of_caller'
end

gem 'curation_concerns', github: 'projecthydra-labs/curation_concerns'

0 comments on commit aac3eb8

Please sign in to comment.