From 7fb4bc903fcc2012a42af63d47f3ed82dfdf583b Mon Sep 17 00:00:00 2001 From: Trey Pendragon Date: Mon, 31 Jul 2017 11:38:02 -0700 Subject: [PATCH] Add collection CRUD --- app/change_sets/collection_change_set.rb | 13 +++++ app/controllers/collections_controller.rb | 10 ++++ app/decorators/collection_decorator.rb | 6 ++ app/models/collection.rb | 9 +++ config/routes.rb | 2 + .../change_sets/collection_change_set_spec.rb | 45 ++++++++++++++ spec/controllers/catalog_controller_spec.rb | 10 ++++ .../collections_controller_spec.rb | 58 +++++++++++++++++++ spec/factories/collection.rb | 12 ++++ spec/models/collection_spec.rb | 22 +++++++ 10 files changed, 187 insertions(+) create mode 100644 app/change_sets/collection_change_set.rb create mode 100644 app/controllers/collections_controller.rb create mode 100644 app/decorators/collection_decorator.rb create mode 100644 app/models/collection.rb create mode 100644 spec/change_sets/collection_change_set_spec.rb create mode 100644 spec/controllers/collections_controller_spec.rb create mode 100644 spec/factories/collection.rb create mode 100644 spec/models/collection_spec.rb diff --git a/app/change_sets/collection_change_set.rb b/app/change_sets/collection_change_set.rb new file mode 100644 index 0000000000..c641c0f97f --- /dev/null +++ b/app/change_sets/collection_change_set.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +class CollectionChangeSet < Valkyrie::ChangeSet + delegate :human_readable_type, to: :model + property :title, multiple: false, required: true + property :slug, multiple: false, required: true + property :description, multiple: false, required: false + property :visibility, multiple: false, required: false + validates :title, :slug, presence: true + + def primary_terms + [:title, :slug, :description] + end +end diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb new file mode 100644 index 0000000000..6603d17924 --- /dev/null +++ b/app/controllers/collections_controller.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +class CollectionsController < ApplicationController + include Valhalla::ResourceController + self.change_set_class = DynamicChangeSet + self.resource_class = Collection + self.change_set_persister = PlumChangeSetPersister.new( + metadata_adapter: Valkyrie::MetadataAdapter.find(:indexing_persister), + storage_adapter: Valkyrie.config.storage_adapter + ) +end diff --git a/app/decorators/collection_decorator.rb b/app/decorators/collection_decorator.rb new file mode 100644 index 0000000000..47713c5038 --- /dev/null +++ b/app/decorators/collection_decorator.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true +class CollectionDecorator < Valkyrie::ResourceDecorator + def manageable_files? + false + end +end diff --git a/app/models/collection.rb b/app/models/collection.rb new file mode 100644 index 0000000000..7f22c89e55 --- /dev/null +++ b/app/models/collection.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true +class Collection < Valhalla::Resource + include Valkyrie::Resource::AccessControls + attribute :id, Valkyrie::Types::ID.optional + attribute :title, Valkyrie::Types::Set + attribute :slug, Valkyrie::Types::Set + attribute :description, Valkyrie::Types::Set + attribute :visibility, Valkyrie::Types::Set +end diff --git a/config/routes.rb b/config/routes.rb index 88ba371314..e07e6d31da 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -66,6 +66,8 @@ end end + resources :collections + get '/catalog/parent/:parent_id/:id', to: 'catalog#show', as: :parent_solr_document mount BrowseEverything::Engine => '/browse' diff --git a/spec/change_sets/collection_change_set_spec.rb b/spec/change_sets/collection_change_set_spec.rb new file mode 100644 index 0000000000..37666b1906 --- /dev/null +++ b/spec/change_sets/collection_change_set_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true +require 'rails_helper' + +RSpec.describe CollectionChangeSet do + subject(:change_set) { described_class.new(collection) } + let(:collection) { FactoryGirl.build(:collection) } + before do + change_set.prepopulate! + end + describe "#title" do + it "is single-valued and required" do + expect(change_set.multiple?(:title)).to eq false + expect(change_set.required?(:title)).to eq true + expect(change_set.validate(title: "")).to eq false + end + end + + describe "#slug" do + it "is single-valued and required" do + expect(change_set.multiple?(:slug)).to eq false + expect(change_set.required?(:slug)).to eq true + expect(change_set.validate(slug: "")).to eq false + end + end + + describe "#description" do + it "is single-valued and not required" do + expect(change_set.multiple?(:description)).to eq false + expect(change_set.required?(:description)).to eq false + end + end + + describe "#visibility" do + it "is single-valued and not required" do + expect(change_set.multiple?(:description)).to eq false + expect(change_set.required?(:description)).to eq false + end + end + + describe "#primary_terms" do + it "returns the primary terms" do + expect(change_set.primary_terms).to eq [:title, :slug, :description] + end + end +end diff --git a/spec/controllers/catalog_controller_spec.rb b/spec/controllers/catalog_controller_spec.rb index cf797d5fcf..621d1db0d1 100644 --- a/spec/controllers/catalog_controller_spec.rb +++ b/spec/controllers/catalog_controller_spec.rb @@ -76,6 +76,16 @@ expect(response.body).to have_link "Delete This File Set", href: file_set_path(resource) expect(response.body).not_to have_link "File Manager" end + + it "renders for a Collection" do + resource = persister.save(resource: FactoryGirl.build(:collection)) + + get :show, params: { id: "id-#{resource.id}" } + + expect(response.body).to have_link "Edit This Collection", href: edit_collection_path(resource) + expect(response.body).to have_link "Delete This Collection", href: collection_path(resource) + expect(response.body).not_to have_link "File Manager" + end end end diff --git a/spec/controllers/collections_controller_spec.rb b/spec/controllers/collections_controller_spec.rb new file mode 100644 index 0000000000..db4c4610b4 --- /dev/null +++ b/spec/controllers/collections_controller_spec.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true +require 'rails_helper' + +RSpec.describe CollectionsController do + let(:user) { nil } + let(:adapter) { Valkyrie::MetadataAdapter.find(:indexing_persister) } + let(:persister) { adapter.persister } + let(:query_service) { adapter.query_service } + before do + sign_in user if user + end + context "when an admin" do + let(:user) { FactoryGirl.create(:admin) } + describe "POST /collections" do + it "creates a collection" do + post :create, params: { collection: { title: 'test', slug: 'slug', visibility: 'open', description: '' } } + + expect(response).to be_redirect + + collection = query_service.find_all_of_model(model: Collection).first + expect(collection.title).to eq ['test'] + expect(collection.slug).to eq ['slug'] + expect(collection.visibility).to eq ['open'] + expect(collection.description).to eq [] + end + end + describe "GET /collections/new" do + render_views + it "renders a new record" do + get :new + + expect(response).to render_template("valhalla/base/_form") + end + end + + describe "GET /collections/edit" do + render_views + it "renders an existing record" do + collection = persister.save(resource: FactoryGirl.build(:collection)) + + get :edit, params: { id: collection.id.to_s } + + expect(response.body).to have_field "Title", with: collection.title.first + end + end + + describe "PATCH /collections/:id" do + it "updates an existing record" do + collection = persister.save(resource: FactoryGirl.build(:collection)) + + patch :update, params: { id: collection.id.to_s, collection: { title: 'New' } } + reloaded = query_service.find_by(id: collection.id) + + expect(reloaded.title).to eq ['New'] + end + end + end +end diff --git a/spec/factories/collection.rb b/spec/factories/collection.rb new file mode 100644 index 0000000000..d0f6921b1d --- /dev/null +++ b/spec/factories/collection.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true +FactoryGirl.define do + factory :collection do + title 'Title' + slug 'test' + visibility 'open' + read_groups 'public' + to_create do |instance| + Valkyrie.config.metadata_adapter.persister.save(resource: instance) + end + end +end diff --git a/spec/models/collection_spec.rb b/spec/models/collection_spec.rb new file mode 100644 index 0000000000..2d41263fb2 --- /dev/null +++ b/spec/models/collection_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +require 'rails_helper' + +RSpec.describe Collection do + subject(:collection) { FactoryGirl.build(:collection) } + it "has a title" do + collection.title = "Test" + expect(collection.title).to eq ["Test"] + end + it "has a slug" do + collection.slug = "test" + expect(collection.slug).to eq ["test"] + end + it "has a description" do + collection.description = "test" + expect(collection.description).to eq ["test"] + end + it "has visibility" do + collection.visibility = "open" + expect(collection.visibility).to eq ["open"] + end +end