valkyrie 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +46 -0
- data/.docker-stack/valkyrie-development/docker-compose.yml +68 -0
- data/.docker-stack/valkyrie-test/docker-compose.yml +68 -0
- data/CHANGELOG.md +13 -0
- data/README.md +50 -11
- data/Rakefile +4 -2
- data/db/config.yml +18 -8
- data/lib/config/database_connection.rb +1 -1
- data/lib/valkyrie/persistence/fedora/permissive_schema.rb +16 -0
- data/lib/valkyrie/persistence/fedora/persister.rb +47 -5
- data/lib/valkyrie/persistence/fedora/persister/alternate_identifier.rb +10 -0
- data/lib/valkyrie/persistence/fedora/query_service.rb +19 -7
- data/lib/valkyrie/persistence/memory/query_service.rb +11 -0
- data/lib/valkyrie/persistence/postgres/query_service.rb +8 -2
- data/lib/valkyrie/persistence/solr/queries.rb +1 -0
- data/lib/valkyrie/persistence/solr/queries/find_by_alternate_identifier_query.rb +26 -0
- data/lib/valkyrie/persistence/solr/query_service.rb +7 -0
- data/lib/valkyrie/persistence/solr/repository.rb +1 -1
- data/lib/valkyrie/specs/shared_specs/queries.rb +40 -0
- data/lib/valkyrie/version.rb +1 -1
- data/tasks/docker.rake +31 -0
- data/valkyrie.gemspec +2 -1
- metadata +26 -7
- data/circle.yml +0 -17
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: fe10f5866474217fe3edb3acce93747447fe6de5c8ad582d0be617f0dd93c040
         | 
| 4 | 
            +
              data.tar.gz: e2210174bf001c9115b14266e388cc2999d0a74c560d8872b554e5c04973eb52
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 72d2fedc30bf650bd3794ab34687a47b071ab41fe1c8b29ebaef582b80616eed7f86aa549bc723976f0655fe9d0e302714294ecfb1a1a2461fb2428f00f4cd7c
         | 
| 7 | 
            +
              data.tar.gz: 76bc7d38aa82f6e6bcc57e6e1d8bb7f762cc0f62d2f571f8e96d6a0a0fb76efab8f73327c86e239dfd65dc43fbe2d1d0798695b0008a3240bef0f7d08edd6c2d
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            version: 2
         | 
| 3 | 
            +
            jobs:
         | 
| 4 | 
            +
              build:
         | 
| 5 | 
            +
                machine: true
         | 
| 6 | 
            +
                steps:
         | 
| 7 | 
            +
                  - checkout
         | 
| 8 | 
            +
                  - run:
         | 
| 9 | 
            +
                      name: Install Docker Compose
         | 
| 10 | 
            +
                      command: |
         | 
| 11 | 
            +
                        curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` > ~/docker-compose
         | 
| 12 | 
            +
                        chmod +x ~/docker-compose
         | 
| 13 | 
            +
                        sudo mv ~/docker-compose /usr/local/bin/docker-compose
         | 
| 14 | 
            +
                  - restore_cache:
         | 
| 15 | 
            +
                     keys:
         | 
| 16 | 
            +
                       - bundle-{{ checksum "Gemfile" }}-{{ checksum "valkyrie.gemspec" }}
         | 
| 17 | 
            +
                       - bundle- # used if checksum fails
         | 
| 18 | 
            +
                  - run: sudo apt-get update && sudo apt-get install -y libpq-dev
         | 
| 19 | 
            +
                  - run:
         | 
| 20 | 
            +
                      name: Install dependencies
         | 
| 21 | 
            +
                      command: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs 4 --retry 3
         | 
| 22 | 
            +
                  - save_cache:
         | 
| 23 | 
            +
                      key: bundle-{{ checksum "Gemfile" }}-{{ checksum "valkyrie.gemspec" }}
         | 
| 24 | 
            +
                      paths:
         | 
| 25 | 
            +
                        - "vendor/bundle"
         | 
| 26 | 
            +
                  - run:
         | 
| 27 | 
            +
                      name: Run Rubocop
         | 
| 28 | 
            +
                      command: bundle exec rake rubocop
         | 
| 29 | 
            +
                  - run:
         | 
| 30 | 
            +
                      name: Run Specs
         | 
| 31 | 
            +
                      command: bundle exec rake docker:spec
         | 
| 32 | 
            +
            workflows:
         | 
| 33 | 
            +
              version: 2
         | 
| 34 | 
            +
              build:
         | 
| 35 | 
            +
                jobs:
         | 
| 36 | 
            +
                  - build
         | 
| 37 | 
            +
              nightly:
         | 
| 38 | 
            +
                triggers:
         | 
| 39 | 
            +
                  - schedule:
         | 
| 40 | 
            +
                      cron: "0 0 * * *"
         | 
| 41 | 
            +
                      filters:
         | 
| 42 | 
            +
                        branches:
         | 
| 43 | 
            +
                          only:
         | 
| 44 | 
            +
                            - master
         | 
| 45 | 
            +
                jobs:
         | 
| 46 | 
            +
                  - build
         | 
| @@ -0,0 +1,68 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            version: '3.4'
         | 
| 3 | 
            +
            volumes:
         | 
| 4 | 
            +
              fedora:
         | 
| 5 | 
            +
              db:
         | 
| 6 | 
            +
              solr_repo:
         | 
| 7 | 
            +
              solr_index:
         | 
| 8 | 
            +
            services:
         | 
| 9 | 
            +
              fedora:
         | 
| 10 | 
            +
                image: nulib/fcrepo4
         | 
| 11 | 
            +
                volumes:
         | 
| 12 | 
            +
                - fedora:/data
         | 
| 13 | 
            +
                ports:
         | 
| 14 | 
            +
                - 8986:8080
         | 
| 15 | 
            +
              db:
         | 
| 16 | 
            +
                image: healthcheck/postgres:alpine
         | 
| 17 | 
            +
                volumes:
         | 
| 18 | 
            +
                - db:/data
         | 
| 19 | 
            +
                environment:
         | 
| 20 | 
            +
                - PGDATA=/data
         | 
| 21 | 
            +
                - POSTGRES_USER=docker
         | 
| 22 | 
            +
                - POSTGRES_PASSWORD=d0ck3r
         | 
| 23 | 
            +
                ports:
         | 
| 24 | 
            +
                - 5433:5432
         | 
| 25 | 
            +
              solr_repo:
         | 
| 26 | 
            +
                image: solr:7.2-alpine
         | 
| 27 | 
            +
                ports:
         | 
| 28 | 
            +
                - 8983:8983
         | 
| 29 | 
            +
                volumes:
         | 
| 30 | 
            +
                - solr_repo:/opt/solr/server/solr/mycores
         | 
| 31 | 
            +
                - "../../solr:/solr_config"
         | 
| 32 | 
            +
                entrypoint:
         | 
| 33 | 
            +
                - docker-entrypoint.sh
         | 
| 34 | 
            +
                - solr-precreate
         | 
| 35 | 
            +
                - blacklight-core
         | 
| 36 | 
            +
                - "/solr_config/config"
         | 
| 37 | 
            +
                healthcheck:
         | 
| 38 | 
            +
                  test:
         | 
| 39 | 
            +
                  - CMD
         | 
| 40 | 
            +
                  - wget
         | 
| 41 | 
            +
                  - "-O"
         | 
| 42 | 
            +
                  - "/dev/null"
         | 
| 43 | 
            +
                  - http://localhost:8983/solr/
         | 
| 44 | 
            +
                  interval: 30s
         | 
| 45 | 
            +
                  timeout: 5s
         | 
| 46 | 
            +
                  retries: 3
         | 
| 47 | 
            +
              solr_index:
         | 
| 48 | 
            +
                image: solr:7.2-alpine
         | 
| 49 | 
            +
                ports:
         | 
| 50 | 
            +
                - 8987:8983
         | 
| 51 | 
            +
                volumes:
         | 
| 52 | 
            +
                - solr_index:/opt/solr/server/solr/mycores
         | 
| 53 | 
            +
                - "../../solr:/solr_config"
         | 
| 54 | 
            +
                entrypoint:
         | 
| 55 | 
            +
                - docker-entrypoint.sh
         | 
| 56 | 
            +
                - solr-precreate
         | 
| 57 | 
            +
                - hydra-dev
         | 
| 58 | 
            +
                - "/solr_config/config"
         | 
| 59 | 
            +
                healthcheck:
         | 
| 60 | 
            +
                  test:
         | 
| 61 | 
            +
                  - CMD
         | 
| 62 | 
            +
                  - wget
         | 
| 63 | 
            +
                  - "-O"
         | 
| 64 | 
            +
                  - "/dev/null"
         | 
| 65 | 
            +
                  - http://localhost:8983/solr/
         | 
| 66 | 
            +
                  interval: 30s
         | 
| 67 | 
            +
                  timeout: 5s
         | 
| 68 | 
            +
                  retries: 3
         | 
| @@ -0,0 +1,68 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            version: '3.4'
         | 
| 3 | 
            +
            volumes:
         | 
| 4 | 
            +
              fedora:
         | 
| 5 | 
            +
              db:
         | 
| 6 | 
            +
              solr_repo:
         | 
| 7 | 
            +
              solr_index:
         | 
| 8 | 
            +
            services:
         | 
| 9 | 
            +
              fedora:
         | 
| 10 | 
            +
                image: nulib/fcrepo4
         | 
| 11 | 
            +
                volumes:
         | 
| 12 | 
            +
                - fedora:/data
         | 
| 13 | 
            +
                ports:
         | 
| 14 | 
            +
                - 8988:8080
         | 
| 15 | 
            +
              db:
         | 
| 16 | 
            +
                image: healthcheck/postgres:alpine
         | 
| 17 | 
            +
                volumes:
         | 
| 18 | 
            +
                - db:/data
         | 
| 19 | 
            +
                environment:
         | 
| 20 | 
            +
                - PGDATA=/data
         | 
| 21 | 
            +
                - POSTGRES_USER=docker
         | 
| 22 | 
            +
                - POSTGRES_PASSWORD=d0ck3r
         | 
| 23 | 
            +
                ports:
         | 
| 24 | 
            +
                - 5434:5432
         | 
| 25 | 
            +
              solr_repo:
         | 
| 26 | 
            +
                image: solr:7.2-alpine
         | 
| 27 | 
            +
                ports:
         | 
| 28 | 
            +
                - 8984:8983
         | 
| 29 | 
            +
                volumes:
         | 
| 30 | 
            +
                - solr_repo:/opt/solr/server/solr/mycores
         | 
| 31 | 
            +
                - "../../solr:/solr_config"
         | 
| 32 | 
            +
                entrypoint:
         | 
| 33 | 
            +
                - docker-entrypoint.sh
         | 
| 34 | 
            +
                - solr-precreate
         | 
| 35 | 
            +
                - blacklight-core-test
         | 
| 36 | 
            +
                - "/solr_config/config"
         | 
| 37 | 
            +
                healthcheck:
         | 
| 38 | 
            +
                  test:
         | 
| 39 | 
            +
                  - CMD
         | 
| 40 | 
            +
                  - wget
         | 
| 41 | 
            +
                  - "-O"
         | 
| 42 | 
            +
                  - "/dev/null"
         | 
| 43 | 
            +
                  - http://localhost:8983/solr/
         | 
| 44 | 
            +
                  interval: 30s
         | 
| 45 | 
            +
                  timeout: 5s
         | 
| 46 | 
            +
                  retries: 3
         | 
| 47 | 
            +
              solr_index:
         | 
| 48 | 
            +
                image: solr:7.2-alpine
         | 
| 49 | 
            +
                ports:
         | 
| 50 | 
            +
                - 8985:8983
         | 
| 51 | 
            +
                volumes:
         | 
| 52 | 
            +
                - solr_index:/opt/solr/server/solr/mycores
         | 
| 53 | 
            +
                - "../../solr:/solr_config"
         | 
| 54 | 
            +
                entrypoint:
         | 
| 55 | 
            +
                - docker-entrypoint.sh
         | 
| 56 | 
            +
                - solr-precreate
         | 
| 57 | 
            +
                - hydra-test
         | 
| 58 | 
            +
                - "/solr_config/config"
         | 
| 59 | 
            +
                healthcheck:
         | 
| 60 | 
            +
                  test:
         | 
| 61 | 
            +
                  - CMD
         | 
| 62 | 
            +
                  - wget
         | 
| 63 | 
            +
                  - "-O"
         | 
| 64 | 
            +
                  - "/dev/null"
         | 
| 65 | 
            +
                  - http://localhost:8983/solr/
         | 
| 66 | 
            +
                  interval: 30s
         | 
| 67 | 
            +
                  timeout: 5s
         | 
| 68 | 
            +
                  retries: 3
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,16 @@ | |
| 1 | 
            +
            # v1.1.0 2018-05-08
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## Changes since last release
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Added `find_by_alternate_identifier` query.
         | 
| 6 | 
            +
                [stkenny](https://github.com/stkenny)
         | 
| 7 | 
            +
            * Added Docker environment for development.
         | 
| 8 | 
            +
                [mbklein](https://github.com/mbklein)
         | 
| 9 | 
            +
            * Fixed README documentation.
         | 
| 10 | 
            +
                [revgum](https://github.com/revgum)
         | 
| 11 | 
            +
            * Deprecated `Valkyrie::Persistence::Fedora::PermissiveSchema.references`
         | 
| 12 | 
            +
            * Deprecated `Valkyrie::Persistence::Fedora::PermissiveSchema.alternate_ids`
         | 
| 13 | 
            +
             | 
| 1 14 | 
             
            # v1.0.0 2018-03-23
         | 
| 2 15 |  | 
| 3 16 | 
             
            ## Changes since last release
         | 
    
        data/README.md
    CHANGED
    
    | @@ -35,7 +35,7 @@ instance with a short name that can be used to refer to it in your application: | |
| 35 35 | 
             
            require 'valkyrie'
         | 
| 36 36 | 
             
            Rails.application.config.to_prepare do
         | 
| 37 37 | 
             
              Valkyrie::MetadataAdapter.register(
         | 
| 38 | 
            -
                Valkyrie::Persistence::Postgres::MetadataAdapter,
         | 
| 38 | 
            +
                Valkyrie::Persistence::Postgres::MetadataAdapter.new,
         | 
| 39 39 | 
             
                :postgres
         | 
| 40 40 | 
             
              )
         | 
| 41 41 |  | 
| @@ -83,20 +83,20 @@ A sample configuration file that configures your application to use different ad | |
| 83 83 |  | 
| 84 84 | 
             
            ```
         | 
| 85 85 | 
             
            development:
         | 
| 86 | 
            -
               | 
| 86 | 
            +
              metadata_adapter: postgres
         | 
| 87 87 | 
             
              storage_adapter: disk
         | 
| 88 88 |  | 
| 89 89 | 
             
            test:
         | 
| 90 | 
            -
               | 
| 90 | 
            +
              metadata_adapter: memory
         | 
| 91 91 | 
             
              storage_adapter: memory
         | 
| 92 92 |  | 
| 93 93 | 
             
            production:
         | 
| 94 | 
            -
               | 
| 94 | 
            +
              metadata_adapter: postgres
         | 
| 95 95 | 
             
              storage_adapter: fedora
         | 
| 96 96 | 
             
            ```
         | 
| 97 97 |  | 
| 98 98 | 
             
            For each environment, you must set two values:
         | 
| 99 | 
            -
            * ` | 
| 99 | 
            +
            * `metadata_adapter` is the store where Valkyrie will put the metadata
         | 
| 100 100 | 
             
            * `storage_adapter` is the store where Valkyrie will put the files
         | 
| 101 101 |  | 
| 102 102 | 
             
            The values are the short names used in your initializer.
         | 
| @@ -120,7 +120,7 @@ end | |
| 120 120 |  | 
| 121 121 | 
             
            #### Work Types Generator
         | 
| 122 122 |  | 
| 123 | 
            -
            To create a custom Valkyrie model in your application, you can use the Rails generator.  For example, to | 
| 123 | 
            +
            To create a custom Valkyrie model in your application, you can use the Rails generator.  For example, to
         | 
| 124 124 | 
             
            generate a model named `FooBar` with an unordered `title` field and an ordered `member_ids` field:
         | 
| 125 125 |  | 
| 126 126 | 
             
            ```
         | 
| @@ -136,15 +136,18 @@ rails generate valkyrie:resource Foo/Bar title member_ids:array | |
| 136 136 | 
             
            ### Read and Write Data
         | 
| 137 137 |  | 
| 138 138 | 
             
            ```
         | 
| 139 | 
            +
            # initialize a metadata adapter
         | 
| 140 | 
            +
            adapter = Valkyrie::MetadataAdapter.find(:postgres)
         | 
| 141 | 
            +
             | 
| 139 142 | 
             
            # create an object
         | 
| 140 143 | 
             
            object1 = MyModel.new title: 'My Cool Object', authors: ['Jones, Alice', 'Smith, Bob']
         | 
| 141 | 
            -
            object1 =  | 
| 144 | 
            +
            object1 = adapter.persister.save(resource: object1)
         | 
| 142 145 |  | 
| 143 146 | 
             
            # load an object from the database
         | 
| 144 | 
            -
            object2 =  | 
| 147 | 
            +
            object2 = adapter.query_service.find_by(id: object1.id)
         | 
| 145 148 |  | 
| 146 149 | 
             
            # load all objects
         | 
| 147 | 
            -
            objects =  | 
| 150 | 
            +
            objects = adapter.query_service.find_all
         | 
| 148 151 |  | 
| 149 152 | 
             
            # load all MyModel objects
         | 
| 150 153 | 
             
            Valkyrie.config.metadata_adapter.query_service.find_all_of_model(model: MyModel)
         | 
| @@ -153,17 +156,53 @@ Valkyrie.config.metadata_adapter.query_service.find_all_of_model(model: MyModel) | |
| 153 156 |  | 
| 154 157 | 
             
            ## Installing a Development environment
         | 
| 155 158 |  | 
| 156 | 
            -
            ###  | 
| 159 | 
            +
            ### Without Docker
         | 
| 160 | 
            +
             | 
| 161 | 
            +
            #### External Requirements
         | 
| 157 162 | 
             
            * PostgreSQL with the uuid-ossp extension.
         | 
| 158 163 | 
             
              * Note: Enabling uuid-ossp requires database superuser privileges.
         | 
| 159 164 | 
             
                * From `psql`: `alter user [username] with superuser;`
         | 
| 160 165 |  | 
| 161 | 
            -
             | 
| 166 | 
            +
            #### To run the test suite
         | 
| 162 167 | 
             
            1. Start Solr and Fedora servers for testing with `rake server:test`
         | 
| 163 168 | 
             
            1. Run `rake db:create` (First time only)
         | 
| 164 169 | 
             
            1. Run `rake db:migrate`
         | 
| 170 | 
            +
             | 
| 171 | 
            +
            ### With Docker
         | 
| 172 | 
            +
             | 
| 173 | 
            +
            #### External Requirements
         | 
| 174 | 
            +
            * [Docker](https://store.docker.com/search?offering=community&type=edition) version >= 17.09.0
         | 
| 175 | 
            +
            *
         | 
| 176 | 
            +
            ### Dependency Setup (Mac OSX)
         | 
| 177 | 
            +
             | 
| 178 | 
            +
            1. `brew install docker`
         | 
| 179 | 
            +
            1. `brew install docker-machine`
         | 
| 180 | 
            +
            1. `brew install docker-compose`
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            ### Starting Docker (Mac OSX)
         | 
| 183 | 
            +
             | 
| 184 | 
            +
            1. `docker-machine create default`
         | 
| 185 | 
            +
            1. `docker-machine start default`
         | 
| 186 | 
            +
            1. `eval "$(docker-machine env)"
         | 
| 187 | 
            +
             | 
| 188 | 
            +
            #### Starting the development mode dependencies
         | 
| 189 | 
            +
            1. Start Solr, Fedora, and PostgreSQL with `rake docker:dev:daemon` (or `rake docker:dev:up` in a separate shell to run them in the foreground)
         | 
| 190 | 
            +
            1. Run `rake db:create db:migrate` to initialize the database
         | 
| 191 | 
            +
            1. Develop!
         | 
| 192 | 
            +
            1. Run `rake docker:dev:down` to stop the server stack
         | 
| 193 | 
            +
               * Development servers maintain data between runs. To clean them out, run `rake docker:dev:clean`
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            #### To run the test suite with all dependencies in one go
         | 
| 196 | 
            +
            1. `rake docker:spec`
         | 
| 197 | 
            +
             | 
| 198 | 
            +
            #### To run the test suite manually
         | 
| 199 | 
            +
            1. Start Solr, Fedora, and PostgreSQL with `rake docker:test:daemon` (or `rake docker:test:up` in a separate shell to run them in the foreground)
         | 
| 200 | 
            +
            1. Run `rake db:create db:migrate` to initialize the database
         | 
| 165 201 | 
             
            1. Run the gem's RSpec test suite with `rspec spec` or `rake`
         | 
| 202 | 
            +
            1. Run `rake docker:test:down` to stop the server stack
         | 
| 203 | 
            +
               * The test stack cleans up after itself on exit.
         | 
| 166 204 |  | 
| 205 | 
            +
            The development and test stacks use fully contained virtual volumes and bind all services to different ports, so they can be running at the same time without issue.
         | 
| 167 206 |  | 
| 168 207 | 
             
            ## License
         | 
| 169 208 |  | 
    
        data/Rakefile
    CHANGED
    
    | @@ -5,7 +5,9 @@ require 'yaml' | |
| 5 5 | 
             
            require 'config/database_connection'
         | 
| 6 6 | 
             
            require 'active_record'
         | 
| 7 7 | 
             
            require 'rubocop/rake_task'
         | 
| 8 | 
            -
            load  | 
| 8 | 
            +
            load 'tasks/dev.rake'
         | 
| 9 | 
            +
            load 'tasks/docker.rake'
         | 
| 10 | 
            +
             | 
| 9 11 | 
             
            RSpec::Core::RakeTask.new(:spec)
         | 
| 10 12 |  | 
| 11 13 | 
             
            task default: :spec
         | 
| @@ -25,7 +27,7 @@ namespace :db do | |
| 25 27 | 
             
              end
         | 
| 26 28 |  | 
| 27 29 | 
             
              task configuration: :environment do
         | 
| 28 | 
            -
                @config = YAML.safe_load(ERB.new(File.read("db/config.yml")).result)[DATABASE_ENV]
         | 
| 30 | 
            +
                @config = YAML.safe_load(ERB.new(File.read("db/config.yml")).result, [], [], true)[DATABASE_ENV]
         | 
| 29 31 | 
             
              end
         | 
| 30 32 |  | 
| 31 33 | 
             
              task configure_connection: :configuration do
         | 
    
        data/db/config.yml
    CHANGED
    
    | @@ -1,17 +1,27 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            <% local = File.exist?('/tmp/.s.PGSQL.5432') && File.stat('/tmp/.s.PGSQL.5432').socket? %>
         | 
| 2 | 
            +
            default: &default
         | 
| 2 3 | 
             
              adapter: postgresql
         | 
| 3 | 
            -
              database: Valkyrie_gem_development
         | 
| 4 4 | 
             
              encoding: utf8
         | 
| 5 5 | 
             
              min_messages: warning
         | 
| 6 6 | 
             
              pool: <%= Integer(ENV.fetch("DB_POOL", 5)) %>
         | 
| 7 7 | 
             
              reaping_frequency: <%= Integer(ENV.fetch("DB_REAPING_FREQUENCY", 10)) %>
         | 
| 8 8 | 
             
              timeout: 5000
         | 
| 9 | 
            +
              <% unless local %>
         | 
| 10 | 
            +
              host: localhost
         | 
| 11 | 
            +
              username: docker
         | 
| 12 | 
            +
              password: d0ck3r
         | 
| 13 | 
            +
              <% end %>
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            development:
         | 
| 16 | 
            +
              <<: *default
         | 
| 17 | 
            +
              database: Valkyrie_gem_development
         | 
| 18 | 
            +
              <% unless local %>
         | 
| 19 | 
            +
              port: 5433
         | 
| 20 | 
            +
              <% end %>
         | 
| 9 21 |  | 
| 10 22 | 
             
            test:
         | 
| 11 | 
            -
               | 
| 12 | 
            -
              encoding: utf8
         | 
| 13 | 
            -
              min_messages: warning
         | 
| 14 | 
            -
              pool: <%= Integer(ENV.fetch("DB_POOL", 5)) %>
         | 
| 15 | 
            -
              reaping_frequency: <%= Integer(ENV.fetch("DB_REAPING_FREQUENCY", 10)) %>
         | 
| 16 | 
            -
              timeout: 5000
         | 
| 23 | 
            +
              <<: *default
         | 
| 17 24 | 
             
              database: Valkyrie_gem_test
         | 
| 25 | 
            +
              <% unless local %>
         | 
| 26 | 
            +
              port: 5434
         | 
| 27 | 
            +
              <% end %>
         | 
| @@ -7,7 +7,7 @@ module DatabaseConnection | |
| 7 7 | 
             
                # Ref https://github.com/puma/puma#clustered-mode
         | 
| 8 8 | 
             
                ActiveSupport.on_load(:active_record) do
         | 
| 9 9 | 
             
                  ::ActiveRecord::Base.connection_pool.disconnect! if ::ActiveRecord::Base.connected?
         | 
| 10 | 
            -
                  ::ActiveRecord::Base.configurations = YAML.safe_load(ERB.new(File.read("db/config.yml")).result) || {}
         | 
| 10 | 
            +
                  ::ActiveRecord::Base.configurations = YAML.safe_load(ERB.new(File.read("db/config.yml")).result, [], [], true) || {}
         | 
| 11 11 | 
             
                  config = ::ActiveRecord::Base.configurations[env.to_s]
         | 
| 12 12 | 
             
                  ::ActiveRecord::Base.establish_connection(config)
         | 
| 13 13 | 
             
                end
         | 
| @@ -22,11 +22,27 @@ module Valkyrie::Persistence::Fedora | |
| 22 22 | 
             
                  uri_for(:id)
         | 
| 23 23 | 
             
                end
         | 
| 24 24 |  | 
| 25 | 
            +
                # @deprecated Please use {.uri_for} instead
         | 
| 26 | 
            +
                def self.alternate_ids
         | 
| 27 | 
            +
                  warn "[DEPRECATION] `alternate_ids` is deprecated and will be removed in the next major release. " \
         | 
| 28 | 
            +
                       "It was never used internally - please use `uri_for(:alternate_ids)` " \
         | 
| 29 | 
            +
                       "Called from #{Gem.location_of_caller.join(':')}"
         | 
| 30 | 
            +
                  uri_for(:alternate_ids)
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 25 33 | 
             
                # @return [RDF::URI]
         | 
| 26 34 | 
             
                def self.member_ids
         | 
| 27 35 | 
             
                  uri_for(:member_ids)
         | 
| 28 36 | 
             
                end
         | 
| 29 37 |  | 
| 38 | 
            +
                # @deprecated Please use {.uri_for} instead
         | 
| 39 | 
            +
                def self.references
         | 
| 40 | 
            +
                  warn "[DEPRECATION] `references` is deprecated and will be removed in the next major release. " \
         | 
| 41 | 
            +
                       "It was never used internally - please use `uri_for(:references)` " \
         | 
| 42 | 
            +
                       "Called from #{Gem.location_of_caller.join(':')}"
         | 
| 43 | 
            +
                  uri_for(:references)
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 30 46 | 
             
                # @return [RDF::URI]
         | 
| 31 47 | 
             
                def self.valkyrie_bool
         | 
| 32 48 | 
             
                  uri_for(:valkyrie_bool)
         | 
| @@ -3,6 +3,7 @@ module Valkyrie::Persistence::Fedora | |
| 3 3 | 
             
              # Persister for Fedora MetadataAdapter.
         | 
| 4 4 | 
             
              class Persister
         | 
| 5 5 | 
             
                require 'valkyrie/persistence/fedora/persister/resource_factory'
         | 
| 6 | 
            +
                require 'valkyrie/persistence/fedora/persister/alternate_identifier'
         | 
| 6 7 | 
             
                attr_reader :adapter
         | 
| 7 8 | 
             
                delegate :connection, :base_path, :resource_factory, to: :adapter
         | 
| 8 9 | 
             
                def initialize(adapter:)
         | 
| @@ -16,14 +17,17 @@ module Valkyrie::Persistence::Fedora | |
| 16 17 | 
             
                  resource.updated_at ||= Time.current
         | 
| 17 18 | 
             
                  ensure_multiple_values!(resource)
         | 
| 18 19 | 
             
                  orm = resource_factory.from_resource(resource: resource)
         | 
| 20 | 
            +
                  alternate_resources = find_or_create_alternate_ids(resource)
         | 
| 21 | 
            +
             | 
| 19 22 | 
             
                  if !orm.new? || resource.id
         | 
| 20 | 
            -
                     | 
| 21 | 
            -
             | 
| 22 | 
            -
                    end
         | 
| 23 | 
            +
                    cleanup_alternate_resources(resource) if alternate_resources
         | 
| 24 | 
            +
                    orm.update { |req| req.headers["Prefer"] = "handling=lenient; received=\"minimal\"" }
         | 
| 23 25 | 
             
                  else
         | 
| 24 26 | 
             
                    orm.create
         | 
| 25 27 | 
             
                  end
         | 
| 26 | 
            -
                  resource_factory.to_resource(object: orm)
         | 
| 28 | 
            +
                  persisted_resource = resource_factory.to_resource(object: orm)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  alternate_resources ? save_reference_to_resource(persisted_resource, alternate_resources) : persisted_resource
         | 
| 27 31 | 
             
                end
         | 
| 28 32 |  | 
| 29 33 | 
             
                # (see Valkyrie::Persistence::Memory::Persister#save_all)
         | 
| @@ -35,8 +39,15 @@ module Valkyrie::Persistence::Fedora | |
| 35 39 |  | 
| 36 40 | 
             
                # (see Valkyrie::Persistence::Memory::Persister#delete)
         | 
| 37 41 | 
             
                def delete(resource:)
         | 
| 42 | 
            +
                  if resource.try(:alternate_ids)
         | 
| 43 | 
            +
                    resource.alternate_ids.each do |alternate_identifier|
         | 
| 44 | 
            +
                      adapter.persister.delete(resource: adapter.query_service.find_by(id: alternate_identifier))
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 38 48 | 
             
                  orm = resource_factory.from_resource(resource: resource)
         | 
| 39 49 | 
             
                  orm.delete
         | 
| 50 | 
            +
             | 
| 40 51 | 
             
                  resource
         | 
| 41 52 | 
             
                end
         | 
| 42 53 |  | 
| @@ -60,10 +71,41 @@ module Valkyrie::Persistence::Fedora | |
| 60 71 | 
             
                private
         | 
| 61 72 |  | 
| 62 73 | 
             
                  def ensure_multiple_values!(resource)
         | 
| 63 | 
            -
                    bad_keys = resource.attributes.except(:internal_resource, :created_at, :updated_at, :new_record, :id).select do |_k, v|
         | 
| 74 | 
            +
                    bad_keys = resource.attributes.except(:internal_resource, :created_at, :updated_at, :new_record, :id, :references).select do |_k, v|
         | 
| 64 75 | 
             
                      !v.nil? && !v.is_a?(Array)
         | 
| 65 76 | 
             
                    end
         | 
| 66 77 | 
             
                    raise ::Valkyrie::Persistence::UnsupportedDatatype, "#{resource}: #{bad_keys.keys} have non-array values, which can not be persisted by Valkyrie. Cast to arrays." unless bad_keys.keys.empty?
         | 
| 67 78 | 
             
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def find_or_create_alternate_ids(resource)
         | 
| 81 | 
            +
                    return nil unless resource.try(:alternate_ids)
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    resource.alternate_ids.map do |alternate_identifier|
         | 
| 84 | 
            +
                      begin
         | 
| 85 | 
            +
                        adapter.query_service.find_by(id: alternate_identifier)
         | 
| 86 | 
            +
                      rescue ::Valkyrie::Persistence::ObjectNotFoundError
         | 
| 87 | 
            +
                        alternate_resource = ::Valkyrie::Persistence::Fedora::AlternateIdentifier.new(id: alternate_identifier)
         | 
| 88 | 
            +
                        adapter.persister.save(resource: alternate_resource)
         | 
| 89 | 
            +
                      end
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                  end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  def cleanup_alternate_resources(updated_resource)
         | 
| 94 | 
            +
                    persisted_resource = adapter.query_service.find_by(id: updated_resource.id)
         | 
| 95 | 
            +
                    removed_identifiers = persisted_resource.alternate_ids - updated_resource.alternate_ids
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                    removed_identifiers.each do |removed_id|
         | 
| 98 | 
            +
                      adapter.persister.delete(resource: adapter.query_service.find_by(id: removed_id))
         | 
| 99 | 
            +
                    end
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  def save_reference_to_resource(resource, alternate_resources)
         | 
| 103 | 
            +
                    alternate_resources.each do |alternate_resource|
         | 
| 104 | 
            +
                      alternate_resource.references = resource.id
         | 
| 105 | 
            +
                      adapter.persister.save(resource: alternate_resource)
         | 
| 106 | 
            +
                    end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                    resource
         | 
| 109 | 
            +
                  end
         | 
| 68 110 | 
             
              end
         | 
| 69 111 | 
             
            end
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require 'valkyrie/resource'
         | 
| 3 | 
            +
            require 'valkyrie/types'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Valkyrie::Persistence::Fedora
         | 
| 6 | 
            +
              class AlternateIdentifier < ::Valkyrie::Resource
         | 
| 7 | 
            +
                attribute :id, ::Valkyrie::Types::ID.optional
         | 
| 8 | 
            +
                attribute :references, ::Valkyrie::Types::ID.optional
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| @@ -10,15 +10,19 @@ module Valkyrie::Persistence::Fedora | |
| 10 10 |  | 
| 11 11 | 
             
                # (see Valkyrie::Persistence::Memory::QueryService#find_by)
         | 
| 12 12 | 
             
                def find_by(id:)
         | 
| 13 | 
            -
                  id = Valkyrie::ID.new(id.to_s) if id.is_a?(String)
         | 
| 14 13 | 
             
                  validate_id(id)
         | 
| 15 14 | 
             
                  uri = adapter.id_to_uri(id)
         | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 15 | 
            +
             | 
| 16 | 
            +
                  resource_from_uri(uri)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                # (see Valkyrie::Persistence::Memory::QueryService#find_by_alternate_identifier)
         | 
| 20 | 
            +
                def find_by_alternate_identifier(alternate_identifier:)
         | 
| 21 | 
            +
                  validate_id(alternate_identifier)
         | 
| 22 | 
            +
                  uri = adapter.id_to_uri(alternate_identifier)
         | 
| 23 | 
            +
                  alternate_id = resource_from_uri(uri).references
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  find_by(id: alternate_id)
         | 
| 22 26 | 
             
                end
         | 
| 23 27 |  | 
| 24 28 | 
             
                # (see Valkyrie::Persistence::Memory::QueryService#find_many_by_ids)
         | 
| @@ -113,9 +117,17 @@ module Valkyrie::Persistence::Fedora | |
| 113 117 | 
             
                private
         | 
| 114 118 |  | 
| 115 119 | 
             
                  def validate_id(id)
         | 
| 120 | 
            +
                    id = Valkyrie::ID.new(id.to_s) if id.is_a?(String)
         | 
| 116 121 | 
             
                    raise ArgumentError, 'id must be a Valkyrie::ID' unless id.is_a? Valkyrie::ID
         | 
| 117 122 | 
             
                  end
         | 
| 118 123 |  | 
| 124 | 
            +
                  def resource_from_uri(uri)
         | 
| 125 | 
            +
                    resource = Ldp::Resource.for(connection, uri, connection.get(uri))
         | 
| 126 | 
            +
                    resource_factory.to_resource(object: resource)
         | 
| 127 | 
            +
                  rescue ::Ldp::Gone, ::Ldp::NotFound
         | 
| 128 | 
            +
                    raise ::Valkyrie::Persistence::ObjectNotFoundError
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
             | 
| 119 131 | 
             
                  def ensure_persisted(resource)
         | 
| 120 132 | 
             
                    raise ArgumentError, 'resource is not saved' unless resource.persisted?
         | 
| 121 133 | 
             
                  end
         | 
| @@ -24,6 +24,17 @@ module Valkyrie::Persistence::Memory | |
| 24 24 | 
             
                  cache[id] || raise(::Valkyrie::Persistence::ObjectNotFoundError)
         | 
| 25 25 | 
             
                end
         | 
| 26 26 |  | 
| 27 | 
            +
                # @param alternate_identifier [Valkyrie::ID] The alternate identifier to query for.
         | 
| 28 | 
            +
                # @raise [Valkyrie::Persistence::ObjectNotFoundError] Raised when the alternate identifier
         | 
| 29 | 
            +
                #   isn't in the persistence backend.
         | 
| 30 | 
            +
                # @raise [ArgumentError] Raised when alternate identifier is not a String or a Valkyrie::ID
         | 
| 31 | 
            +
                # @return [Valkyrie::Resource] The object being searched for.
         | 
| 32 | 
            +
                def find_by_alternate_identifier(alternate_identifier:)
         | 
| 33 | 
            +
                  alternate_identifier = Valkyrie::ID.new(alternate_identifier.to_s) if alternate_identifier.is_a?(String)
         | 
| 34 | 
            +
                  validate_id(alternate_identifier)
         | 
| 35 | 
            +
                  cache.select { |_key, resource| resource['alternate_ids'].include?(alternate_identifier) }.values.first || raise(::Valkyrie::Persistence::ObjectNotFoundError)
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 27 38 | 
             
                # @param ids [Array<Valkyrie::ID, String>] The IDs to query for.
         | 
| 28 39 | 
             
                # @raise [ArgumentError] Raised when any ID is not a String or a Valkyrie::ID
         | 
| 29 40 | 
             
                # @return [Array<Valkyrie::Resource>] All requested objects that were found
         | 
| @@ -37,6 +37,14 @@ module Valkyrie::Persistence::Postgres | |
| 37 37 | 
             
                  raise Valkyrie::Persistence::ObjectNotFoundError
         | 
| 38 38 | 
             
                end
         | 
| 39 39 |  | 
| 40 | 
            +
                # (see Valkyrie::Persistence::Memory::QueryService#find_by_alternate_identifier)
         | 
| 41 | 
            +
                def find_by_alternate_identifier(alternate_identifier:)
         | 
| 42 | 
            +
                  alternate_identifier = Valkyrie::ID.new(alternate_identifier.to_s) if alternate_identifier.is_a?(String)
         | 
| 43 | 
            +
                  validate_id(alternate_identifier)
         | 
| 44 | 
            +
                  internal_array = "{\"alternate_ids\": [{\"id\": \"#{alternate_identifier}\"}]}"
         | 
| 45 | 
            +
                  run_query(find_inverse_references_query, internal_array).first || raise(Valkyrie::Persistence::ObjectNotFoundError)
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 40 48 | 
             
                # (see Valkyrie::Persistence::Memory::QueryService#find_many_by_ids)
         | 
| 41 49 | 
             
                def find_many_by_ids(ids:)
         | 
| 42 50 | 
             
                  ids.map! do |id|
         | 
| @@ -48,8 +56,6 @@ module Valkyrie::Persistence::Postgres | |
| 48 56 | 
             
                  orm_class.where(id: ids).map do |orm_resource|
         | 
| 49 57 | 
             
                    resource_factory.to_resource(object: orm_resource)
         | 
| 50 58 | 
             
                  end
         | 
| 51 | 
            -
                rescue ActiveRecord::RecordNotFound
         | 
| 52 | 
            -
                  raise Valkyrie::Persistence::ObjectNotFoundError
         | 
| 53 59 | 
             
                end
         | 
| 54 60 |  | 
| 55 61 | 
             
                # (see Valkyrie::Persistence::Memory::QueryService#find_members)
         | 
| @@ -6,6 +6,7 @@ module Valkyrie::Persistence::Solr | |
| 6 6 | 
             
                require 'valkyrie/persistence/solr/queries/default_paginator'
         | 
| 7 7 | 
             
                require 'valkyrie/persistence/solr/queries/find_all_query'
         | 
| 8 8 | 
             
                require 'valkyrie/persistence/solr/queries/find_by_id_query'
         | 
| 9 | 
            +
                require 'valkyrie/persistence/solr/queries/find_by_alternate_identifier_query'
         | 
| 9 10 | 
             
                require 'valkyrie/persistence/solr/queries/find_many_by_ids_query'
         | 
| 10 11 | 
             
                require 'valkyrie/persistence/solr/queries/find_inverse_references_query'
         | 
| 11 12 | 
             
                require 'valkyrie/persistence/solr/queries/find_members_query'
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module Valkyrie::Persistence::Solr::Queries
         | 
| 3 | 
            +
              # Responsible for returning a single resource identified by an ID.
         | 
| 4 | 
            +
              class FindByAlternateIdentifierQuery
         | 
| 5 | 
            +
                attr_reader :connection, :resource_factory
         | 
| 6 | 
            +
                attr_writer :alternate_identifier
         | 
| 7 | 
            +
                def initialize(alternate_identifier, connection:, resource_factory:)
         | 
| 8 | 
            +
                  @alternate_identifier = alternate_identifier
         | 
| 9 | 
            +
                  @connection = connection
         | 
| 10 | 
            +
                  @resource_factory = resource_factory
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def run
         | 
| 14 | 
            +
                  raise ::Valkyrie::Persistence::ObjectNotFoundError unless resource
         | 
| 15 | 
            +
                  resource_factory.to_resource(object: resource)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def alternate_identifier
         | 
| 19 | 
            +
                  @alternate_identifier.to_s
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def resource
         | 
| 23 | 
            +
                  connection.get("select", params: { q: "alternate_ids_ssim:\"id-#{alternate_identifier}\"", fl: "*", rows: 1 })["response"]["docs"].first
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
| @@ -18,6 +18,13 @@ module Valkyrie::Persistence::Solr | |
| 18 18 | 
             
                  Valkyrie::Persistence::Solr::Queries::FindByIdQuery.new(id, connection: connection, resource_factory: resource_factory).run
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 | 
            +
                # (see Valkyrie::Persistence::Memory::QueryService#find_by_alternate_identifier)
         | 
| 22 | 
            +
                def find_by_alternate_identifier(alternate_identifier:)
         | 
| 23 | 
            +
                  alternate_identifier = Valkyrie::ID.new(alternate_identifier.to_s) if alternate_identifier.is_a?(String)
         | 
| 24 | 
            +
                  validate_id(alternate_identifier)
         | 
| 25 | 
            +
                  Valkyrie::Persistence::Solr::Queries::FindByAlternateIdentifierQuery.new(alternate_identifier, connection: connection, resource_factory: resource_factory).run
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 21 28 | 
             
                # (see Valkyrie::Persistence::Memory::QueryService#find_many_by_ids)
         | 
| 22 29 | 
             
                def find_many_by_ids(ids:)
         | 
| 23 30 | 
             
                  ids.map! do |id|
         | 
| @@ -39,7 +39,7 @@ module Valkyrie::Persistence::Solr | |
| 39 39 | 
             
                end
         | 
| 40 40 |  | 
| 41 41 | 
             
                def ensure_multiple_values!(resource)
         | 
| 42 | 
            -
                  bad_keys = resource.attributes.except(:internal_resource, :created_at, :updated_at, :new_record, :id).select do |_k, v|
         | 
| 42 | 
            +
                  bad_keys = resource.attributes.except(:internal_resource, :alternate_ids, :created_at, :updated_at, :new_record, :id).select do |_k, v|
         | 
| 43 43 | 
             
                    !v.nil? && !v.is_a?(Array)
         | 
| 44 44 | 
             
                  end
         | 
| 45 45 | 
             
                  raise ::Valkyrie::Persistence::UnsupportedDatatype, "#{resource}: #{bad_keys.keys} have non-array values, which can not be persisted by Valkyrie. Cast to arrays." unless bad_keys.keys.empty?
         | 
| @@ -5,6 +5,7 @@ RSpec.shared_examples 'a Valkyrie query provider' do | |
| 5 5 | 
             
                  defined? adapter
         | 
| 6 6 | 
             
                class CustomResource < Valkyrie::Resource
         | 
| 7 7 | 
             
                  attribute :id, Valkyrie::Types::ID.optional
         | 
| 8 | 
            +
                  attribute :alternate_ids, Valkyrie::Types::Array
         | 
| 8 9 | 
             
                  attribute :title
         | 
| 9 10 | 
             
                  attribute :member_ids, Valkyrie::Types::Array
         | 
| 10 11 | 
             
                  attribute :a_member_of
         | 
| @@ -25,6 +26,7 @@ RSpec.shared_examples 'a Valkyrie query provider' do | |
| 25 26 | 
             
              it { is_expected.to respond_to(:find_all).with(0).arguments }
         | 
| 26 27 | 
             
              it { is_expected.to respond_to(:find_all_of_model).with_keywords(:model) }
         | 
| 27 28 | 
             
              it { is_expected.to respond_to(:find_by).with_keywords(:id) }
         | 
| 29 | 
            +
              it { is_expected.to respond_to(:find_by_alternate_identifier).with_keywords(:alternate_identifier) }
         | 
| 28 30 | 
             
              it { is_expected.to respond_to(:find_many_by_ids).with_keywords(:ids) }
         | 
| 29 31 | 
             
              it { is_expected.to respond_to(:find_members).with_keywords(:resource, :model) }
         | 
| 30 32 | 
             
              it { is_expected.to respond_to(:find_references_by).with_keywords(:resource, :property) }
         | 
| @@ -74,6 +76,44 @@ RSpec.shared_examples 'a Valkyrie query provider' do | |
| 74 76 | 
             
                end
         | 
| 75 77 | 
             
              end
         | 
| 76 78 |  | 
| 79 | 
            +
              describe ".find_by_alternate_identifier" do
         | 
| 80 | 
            +
                it "returns a resource by alternate identifier or string representation of an alternate identifier" do
         | 
| 81 | 
            +
                  resource = resource_class.new
         | 
| 82 | 
            +
                  resource.alternate_ids = [Valkyrie::ID.new('p9s0xfj')]
         | 
| 83 | 
            +
                  resource = persister.save(resource: resource)
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  found = query_service.find_by_alternate_identifier(alternate_identifier: resource.alternate_ids.first)
         | 
| 86 | 
            +
                  expect(found.id).to eq resource.id
         | 
| 87 | 
            +
                  expect(found).to be_persisted
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  found = query_service.find_by_alternate_identifier(alternate_identifier: resource.alternate_ids.first.to_s)
         | 
| 90 | 
            +
                  expect(found.id).to eq resource.id
         | 
| 91 | 
            +
                  expect(found).to be_persisted
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                it "returns a Valkyrie::Persistence::ObjectNotFoundError for a non-found alternate identifier" do
         | 
| 95 | 
            +
                  expect { query_service.find_by_alternate_identifier(alternate_identifier: Valkyrie::ID.new("123123123")) }.to raise_error ::Valkyrie::Persistence::ObjectNotFoundError
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                it 'raises an error if the alternate identifier is not a Valkyrie::ID or a string' do
         | 
| 99 | 
            +
                  expect { query_service.find_by_alternate_identifier(alternate_identifier: 123) }.to raise_error ArgumentError
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                it 'can have multiple alternate identifiers' do
         | 
| 103 | 
            +
                  resource = resource_class.new
         | 
| 104 | 
            +
                  resource.alternate_ids = [Valkyrie::ID.new('p9s0xfj'), Valkyrie::ID.new('jks0xfj')]
         | 
| 105 | 
            +
                  resource = persister.save(resource: resource)
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  found = query_service.find_by_alternate_identifier(alternate_identifier: resource.alternate_ids.first)
         | 
| 108 | 
            +
                  expect(found.id).to eq resource.id
         | 
| 109 | 
            +
                  expect(found).to be_persisted
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  found = query_service.find_by_alternate_identifier(alternate_identifier: resource.alternate_ids.last)
         | 
| 112 | 
            +
                  expect(found.id).to eq resource.id
         | 
| 113 | 
            +
                  expect(found).to be_persisted
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
              end
         | 
| 116 | 
            +
             | 
| 77 117 | 
             
              describe ".find_many_by_ids" do
         | 
| 78 118 | 
             
                let!(:resource) { persister.save(resource: resource_class.new) }
         | 
| 79 119 | 
             
                let!(:resource2) { persister.save(resource: resource_class.new) }
         | 
    
        data/lib/valkyrie/version.rb
    CHANGED
    
    
    
        data/tasks/docker.rake
    ADDED
    
    | @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require 'valkyrie'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            if Rails.env.development? || Rails.env.test?
         | 
| 5 | 
            +
              begin
         | 
| 6 | 
            +
                require 'docker/stack/rake_task'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def get_named_task(task_name)
         | 
| 9 | 
            +
                  Rake::Task[task_name]
         | 
| 10 | 
            +
                rescue RuntimeError
         | 
| 11 | 
            +
                  nil
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                namespace :docker do
         | 
| 15 | 
            +
                  namespace(:dev)  { Docker::Stack::RakeTask.load_tasks }
         | 
| 16 | 
            +
                  namespace(:test) { Docker::Stack::RakeTask.load_tasks(force_env: 'test', cleanup: true) }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  desc 'Spin up test stack and run specs'
         | 
| 19 | 
            +
                  task :spec do
         | 
| 20 | 
            +
                    Rails.env = 'test'
         | 
| 21 | 
            +
                    Docker::Stack::Controller.new(project: 'valkyrie', cleanup: true).with_containers do
         | 
| 22 | 
            +
                      Rake::Task['db:create'].invoke
         | 
| 23 | 
            +
                      Rake::Task['db:migrate'].invoke
         | 
| 24 | 
            +
                      Rake::Task['spec'].invoke
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              rescue LoadError
         | 
| 29 | 
            +
                Rails.logger.warn 'Docker rake tasks not loaded.'
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
    
        data/valkyrie.gemspec
    CHANGED
    
    | @@ -22,7 +22,7 @@ Gem::Specification.new do |spec| | |
| 22 22 | 
             
              spec.add_dependency 'dry-struct'
         | 
| 23 23 | 
             
              spec.add_dependency 'draper'
         | 
| 24 24 | 
             
              spec.add_dependency 'activemodel'
         | 
| 25 | 
            -
              spec.add_dependency 'dry-types'
         | 
| 25 | 
            +
              spec.add_dependency 'dry-types', '~> 0.12.0'
         | 
| 26 26 | 
             
              spec.add_dependency 'rdf'
         | 
| 27 27 | 
             
              spec.add_dependency 'active-fedora'
         | 
| 28 28 | 
             
              spec.add_dependency 'activesupport'
         | 
| @@ -49,4 +49,5 @@ Gem::Specification.new do |spec| | |
| 49 49 | 
             
              spec.add_development_dependency 'yard'
         | 
| 50 50 | 
             
              spec.add_development_dependency 'solr_wrapper'
         | 
| 51 51 | 
             
              spec.add_development_dependency 'fcrepo_wrapper'
         | 
| 52 | 
            +
              spec.add_development_dependency 'docker-stack', '~> 0.2.6'
         | 
| 52 53 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: valkyrie
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.1.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Trey Pendragon
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2018- | 
| 11 | 
            +
            date: 2018-05-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: dry-struct
         | 
| @@ -56,16 +56,16 @@ dependencies: | |
| 56 56 | 
             
              name: dry-types
         | 
| 57 57 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 58 | 
             
                requirements:
         | 
| 59 | 
            -
                - - " | 
| 59 | 
            +
                - - "~>"
         | 
| 60 60 | 
             
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            -
                    version:  | 
| 61 | 
            +
                    version: 0.12.0
         | 
| 62 62 | 
             
              type: :runtime
         | 
| 63 63 | 
             
              prerelease: false
         | 
| 64 64 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 65 | 
             
                requirements:
         | 
| 66 | 
            -
                - - " | 
| 66 | 
            +
                - - "~>"
         | 
| 67 67 | 
             
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            -
                    version:  | 
| 68 | 
            +
                    version: 0.12.0
         | 
| 69 69 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 70 70 | 
             
              name: rdf
         | 
| 71 71 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -388,6 +388,20 @@ dependencies: | |
| 388 388 | 
             
                - - ">="
         | 
| 389 389 | 
             
                  - !ruby/object:Gem::Version
         | 
| 390 390 | 
             
                    version: '0'
         | 
| 391 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 392 | 
            +
              name: docker-stack
         | 
| 393 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 394 | 
            +
                requirements:
         | 
| 395 | 
            +
                - - "~>"
         | 
| 396 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 397 | 
            +
                    version: 0.2.6
         | 
| 398 | 
            +
              type: :development
         | 
| 399 | 
            +
              prerelease: false
         | 
| 400 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 401 | 
            +
                requirements:
         | 
| 402 | 
            +
                - - "~>"
         | 
| 403 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 404 | 
            +
                    version: 0.2.6
         | 
| 391 405 | 
             
            description: 
         | 
| 392 406 | 
             
            email:
         | 
| 393 407 | 
             
            - tpendragon@princeton.edu
         | 
| @@ -395,7 +409,10 @@ executables: [] | |
| 395 409 | 
             
            extensions: []
         | 
| 396 410 | 
             
            extra_rdoc_files: []
         | 
| 397 411 | 
             
            files:
         | 
| 412 | 
            +
            - ".circleci/config.yml"
         | 
| 398 413 | 
             
            - ".ctags"
         | 
| 414 | 
            +
            - ".docker-stack/valkyrie-development/docker-compose.yml"
         | 
| 415 | 
            +
            - ".docker-stack/valkyrie-test/docker-compose.yml"
         | 
| 399 416 | 
             
            - ".gitignore"
         | 
| 400 417 | 
             
            - ".rspec"
         | 
| 401 418 | 
             
            - ".rubocop.yml"
         | 
| @@ -410,7 +427,6 @@ files: | |
| 410 427 | 
             
            - bin/rspec
         | 
| 411 428 | 
             
            - bin/setup
         | 
| 412 429 | 
             
            - browserslist
         | 
| 413 | 
            -
            - circle.yml
         | 
| 414 430 | 
             
            - config/fedora.yml
         | 
| 415 431 | 
             
            - config/valkyrie.yml
         | 
| 416 432 | 
             
            - db/config.yml
         | 
| @@ -446,6 +462,7 @@ files: | |
| 446 462 | 
             
            - lib/valkyrie/persistence/fedora/ordered_reader.rb
         | 
| 447 463 | 
             
            - lib/valkyrie/persistence/fedora/permissive_schema.rb
         | 
| 448 464 | 
             
            - lib/valkyrie/persistence/fedora/persister.rb
         | 
| 465 | 
            +
            - lib/valkyrie/persistence/fedora/persister/alternate_identifier.rb
         | 
| 449 466 | 
             
            - lib/valkyrie/persistence/fedora/persister/model_converter.rb
         | 
| 450 467 | 
             
            - lib/valkyrie/persistence/fedora/persister/orm_converter.rb
         | 
| 451 468 | 
             
            - lib/valkyrie/persistence/fedora/persister/resource_factory.rb
         | 
| @@ -472,6 +489,7 @@ files: | |
| 472 489 | 
             
            - lib/valkyrie/persistence/solr/queries.rb
         | 
| 473 490 | 
             
            - lib/valkyrie/persistence/solr/queries/default_paginator.rb
         | 
| 474 491 | 
             
            - lib/valkyrie/persistence/solr/queries/find_all_query.rb
         | 
| 492 | 
            +
            - lib/valkyrie/persistence/solr/queries/find_by_alternate_identifier_query.rb
         | 
| 475 493 | 
             
            - lib/valkyrie/persistence/solr/queries/find_by_id_query.rb
         | 
| 476 494 | 
             
            - lib/valkyrie/persistence/solr/queries/find_inverse_references_query.rb
         | 
| 477 495 | 
             
            - lib/valkyrie/persistence/solr/queries/find_many_by_ids_query.rb
         | 
| @@ -519,6 +537,7 @@ files: | |
| 519 537 | 
             
            - solr/config/xslt/luke.xsl
         | 
| 520 538 | 
             
            - solr/solr.xml
         | 
| 521 539 | 
             
            - tasks/dev.rake
         | 
| 540 | 
            +
            - tasks/docker.rake
         | 
| 522 541 | 
             
            - valkyrie.gemspec
         | 
| 523 542 | 
             
            homepage: 
         | 
| 524 543 | 
             
            licenses: []
         | 
    
        data/circle.yml
    DELETED
    
    | @@ -1,17 +0,0 @@ | |
| 1 | 
            -
            machine:
         | 
| 2 | 
            -
              ruby:
         | 
| 3 | 
            -
                version: 2.3.1
         | 
| 4 | 
            -
              services:
         | 
| 5 | 
            -
                - redis
         | 
| 6 | 
            -
            general:
         | 
| 7 | 
            -
              artifacts:
         | 
| 8 | 
            -
                - "tmp/capybara"
         | 
| 9 | 
            -
            dependencies:
         | 
| 10 | 
            -
              post:
         | 
| 11 | 
            -
                - bundle exec rake rubocop
         | 
| 12 | 
            -
                - bundle exec rake server:test:
         | 
| 13 | 
            -
                    background: true
         | 
| 14 | 
            -
                - bin/jetty_wait
         | 
| 15 | 
            -
            notify:
         | 
| 16 | 
            -
              webhooks:
         | 
| 17 | 
            -
                - url: https://coveralls.io/webhook?repo_token=c3AnaQOFVYYTitAR1w6ySNScXSIfLQwN4
         |