valkyrie 2.0.0.RC5 → 2.0.0.RC6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +9 -9
- data/CHANGELOG.md +72 -0
- data/README.md +4 -4
- data/lib/valkyrie.rb +0 -2
- data/lib/valkyrie/change_set.rb +9 -0
- data/lib/valkyrie/persistence.rb +1 -0
- data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +2 -2
- data/lib/valkyrie/persistence/fedora/query_service.rb +1 -1
- data/lib/valkyrie/persistence/memory/query_service.rb +1 -1
- data/lib/valkyrie/persistence/postgres/orm_converter.rb +1 -151
- data/lib/valkyrie/persistence/postgres/query_service.rb +1 -1
- data/lib/valkyrie/persistence/shared.rb +6 -0
- data/lib/valkyrie/persistence/shared/json_value_mapper.rb +157 -0
- data/lib/valkyrie/persistence/solr/query_service.rb +1 -1
- data/lib/valkyrie/resource.rb +17 -14
- data/lib/valkyrie/specs/shared_specs/resource.rb +27 -6
- data/lib/valkyrie/types.rb +4 -11
- data/lib/valkyrie/version.rb +1 -1
- data/valkyrie.gemspec +2 -1
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1336b38de11dafb9436b6f04cf20438f2bbdde2662a9f1e4fb17214b29b2628e
|
4
|
+
data.tar.gz: bf96fa3e361a65d700d01a293f149c62f27b48ea3a952b60bdc2e5907ab4a86d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 838ce2eda7f2966055f0b26d467ca92d567c90372b2a020b4eab64fc86d7cfdca7a9f7d0775885a101e19b1885682beeb1a49386e934a41eca2b6b7f23492878
|
7
|
+
data.tar.gz: 5a8567646b98d942e96582a0212b823f23d603c18fe25c5e78284bd5e73f9aed4867c7c1ab0559ce8f8235d452e7f3c23cc73ffc39ff6c4feeb83693fc2bf188
|
data/.circleci/config.yml
CHANGED
@@ -10,7 +10,7 @@ jobs:
|
|
10
10
|
type: "string"
|
11
11
|
ruby:
|
12
12
|
description: "Ruby version"
|
13
|
-
default: "2.6.
|
13
|
+
default: "2.6.3"
|
14
14
|
type: "string"
|
15
15
|
environment:
|
16
16
|
BUNDLE_GEMFILE: << parameters.gemfile >>
|
@@ -69,11 +69,11 @@ workflows:
|
|
69
69
|
jobs:
|
70
70
|
- build:
|
71
71
|
gemfile: "gemfiles/activerecord_5_2.gemfile"
|
72
|
-
ruby: 2.6.
|
72
|
+
ruby: 2.6.3
|
73
73
|
name: "Ruby2-6_Rails5-2"
|
74
74
|
- build:
|
75
75
|
gemfile: "gemfiles/activerecord_5_1.gemfile"
|
76
|
-
ruby: 2.6.
|
76
|
+
ruby: 2.6.3
|
77
77
|
name: "Ruby2-6_Rails5-1"
|
78
78
|
- build:
|
79
79
|
gemfile: "gemfiles/activerecord_5_2.gemfile"
|
@@ -85,11 +85,11 @@ workflows:
|
|
85
85
|
name: "Ruby2-5_Rails5-1"
|
86
86
|
- build:
|
87
87
|
gemfile: "gemfiles/activerecord_5_2.gemfile"
|
88
|
-
ruby: 2.4.
|
88
|
+
ruby: 2.4.6
|
89
89
|
name: "Ruby2-4_Rails5-2"
|
90
90
|
- build:
|
91
91
|
gemfile: "gemfiles/activerecord_5_1.gemfile"
|
92
|
-
ruby: 2.4.
|
92
|
+
ruby: 2.4.6
|
93
93
|
name: "Ruby2-4_Rails5-1"
|
94
94
|
nightly:
|
95
95
|
triggers:
|
@@ -102,11 +102,11 @@ workflows:
|
|
102
102
|
jobs:
|
103
103
|
- build:
|
104
104
|
gemfile: "gemfiles/activerecord_5_2.gemfile"
|
105
|
-
ruby: 2.6.
|
105
|
+
ruby: 2.6.3
|
106
106
|
name: "Ruby2-6_Rails5-2"
|
107
107
|
- build:
|
108
108
|
gemfile: "gemfiles/activerecord_5_1.gemfile"
|
109
|
-
ruby: 2.6.
|
109
|
+
ruby: 2.6.3
|
110
110
|
name: "Ruby2-6_Rails5-1"
|
111
111
|
- build:
|
112
112
|
gemfile: "gemfiles/activerecord_5_2.gemfile"
|
@@ -118,9 +118,9 @@ workflows:
|
|
118
118
|
name: "Ruby2-5_Rails5-1"
|
119
119
|
- build:
|
120
120
|
gemfile: "gemfiles/activerecord_5_2.gemfile"
|
121
|
-
ruby: 2.4.
|
121
|
+
ruby: 2.4.6
|
122
122
|
name: "Ruby2-4_Rails5-2"
|
123
123
|
- build:
|
124
124
|
gemfile: "gemfiles/activerecord_5_1.gemfile"
|
125
|
-
ruby: 2.4.
|
125
|
+
ruby: 2.4.6
|
126
126
|
name: "Ruby2-4_Rails5-1"
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,75 @@
|
|
1
|
+
# v2.0.0 2018-04-27
|
2
|
+
|
3
|
+
## Changes since last release
|
4
|
+
|
5
|
+
* Make LDP optional (Add `gem ldp` to Gemfile if using Fedora)
|
6
|
+
* Make ActiveRecord optional (Add `gem activerecord` to Gemfile if using
|
7
|
+
Postgres)
|
8
|
+
* Make RSolr optional (Add `gem rsolr` to Gemfile if using Solr)
|
9
|
+
* Remove deprecated `standardize_query_result` argument.
|
10
|
+
* Remove deprecated `Valkyrie::ID#to_uri`
|
11
|
+
* Remove ActiveFedora as a dependency.
|
12
|
+
* Remove deprecated `Valkyrie::Persistence::Fedora::PermissiveSchema.alternate_ids`
|
13
|
+
* Remove deprecated `Valkyrie::Persistence::Fedora::PermissiveSchema.references`
|
14
|
+
* Upgrade `dry-types` to `0.13.x`
|
15
|
+
* Fedora Adapter default is now version 5.
|
16
|
+
* Require a symbol key when instantiating a Valkyrie::Resource (string keys are no longer valid)
|
17
|
+
* Remove deprecated `type.member()` method (use `type.of()`)
|
18
|
+
* Remove deprecated `Valkyrie::Types::Int` (use `Valkyrie::Types::Integer`)
|
19
|
+
|
20
|
+
## Changes Without Deprecations in `1.6.0`
|
21
|
+
|
22
|
+
1. Overriding an attribute getter no longer changes the output of `to_h`. If
|
23
|
+
you've overridden something via `def title; "overwritten"; end`, then `to_h`
|
24
|
+
will now have what was set via the setter or initializer, not `overwritten`.
|
25
|
+
2. Setting attribute values via overriding instance variables no longer works.
|
26
|
+
Please use `#set_value` if you need dynamic setting, as this will be a stable
|
27
|
+
API.
|
28
|
+
3. `Valkyrie::Resource#to_h` no longer includes keys with `nil` values.
|
29
|
+
|
30
|
+
## Upgrade Guide
|
31
|
+
|
32
|
+
1. Upgrade Valkyrie to `1.6.0` in your application, run tests, and fix all
|
33
|
+
deprecations output to console.
|
34
|
+
2. Upgrade Valkyrie to `2.0.0` in your application.
|
35
|
+
3. Failing tests at this point are likely due to behavior in the "Changes
|
36
|
+
Without Deprecations" section above. If you have any trouble, please contact
|
37
|
+
us in the #valkyrie channel in [Samvera Slack](http://slack.samvera.org/).
|
38
|
+
|
39
|
+
## New Product Owner
|
40
|
+
|
41
|
+
All of us who have been part of the Valkyrie project so far would like to thank
|
42
|
+
[Carolyn Cole](https://github.com/carolyncole) for her role so far as Product Owner.
|
43
|
+
We'd like to welcome [Kate Lynch](https://github.com/kelynch), who will be
|
44
|
+
taking over effective immediately!
|
45
|
+
|
46
|
+
## Special Thanks
|
47
|
+
|
48
|
+
This is the first major version of Valkyrie since 1.0 over a year ago. A lot of
|
49
|
+
work has gone into it, and I'd like to take the chance to thank everyone
|
50
|
+
involved for their contributions in the last year:
|
51
|
+
|
52
|
+
|
53
|
+
[DanCoughlin](https://github.com/DanCoughlin)
|
54
|
+
[awead](https://github.com/awead)
|
55
|
+
[cam156](https://github.com/cam156)
|
56
|
+
[carolyncole](https://github.com/carolyncole)
|
57
|
+
[cjcolvar](https://github.com/cjcolvar)
|
58
|
+
[dgcliff](https://github.com/dgcliff)
|
59
|
+
[escowles](https://github.com/escowles)
|
60
|
+
[hackmastera](https://github.com/hackmastera)
|
61
|
+
[jeremyf](https://github.com/jeremyf)
|
62
|
+
[jrgriffiniii](https://github.com/jrgriffiniii)
|
63
|
+
[kelynch](https://github.com/kelynch)
|
64
|
+
[mbklein](https://github.com/mbklein)
|
65
|
+
[mjgiarlo](https://github.com/mjgiarlo)
|
66
|
+
[mtribone](https://github.com/mtribone)
|
67
|
+
[no-reply](https://github.com/no-reply)
|
68
|
+
[ojlyytinen](https://github.com/ojlyytinen)
|
69
|
+
[revgum](https://github.com/revgum)
|
70
|
+
[stkenny](https://github.com/stkenny)
|
71
|
+
[tpendragon](https://github.com/tpendragon)
|
72
|
+
|
1
73
|
# v1.6.0 2018-04-17
|
2
74
|
|
3
75
|
## Changes since last release
|
data/README.md
CHANGED
@@ -17,7 +17,7 @@ Jump in: [![Slack Status](http://slack.samvera.org/badge.svg)](http://slack.samv
|
|
17
17
|
## Primary Contacts
|
18
18
|
|
19
19
|
### Product Owner
|
20
|
-
[
|
20
|
+
[Kate Lynch](https://github.com/kelynch)
|
21
21
|
|
22
22
|
### Technical Lead
|
23
23
|
[Trey Pendragon](https://github.com/tpendragon)
|
@@ -103,11 +103,11 @@ end
|
|
103
103
|
```
|
104
104
|
|
105
105
|
The initializer registers four `Valkyrie::MetadataAdapter` instances for storing metadata:
|
106
|
-
* `:postgres` which stores metadata in a PostgreSQL database
|
107
|
-
* `:solr` which stores metadata in a Solr Index
|
108
106
|
* `:fedora` which stores metadata in a Fedora server.
|
109
107
|
* `:memory` which stores metadata in an in-memory cache (this cache is not persistent, so it is only
|
110
|
-
appropriate for testing)
|
108
|
+
appropriate for testing).
|
109
|
+
* `:postgres` which stores metadata in a PostgreSQL database.
|
110
|
+
* `:solr` which stores metadata in a Solr Index.
|
111
111
|
|
112
112
|
Other adapter options include `Valkyrie::Persistence::BufferedPersister` for buffering in memory before bulk
|
113
113
|
updating another persister, `Valkyrie::Persistence::CompositePersister` for storing in more than one adapter
|
data/lib/valkyrie.rb
CHANGED
data/lib/valkyrie/change_set.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'reform/form/coercion'
|
3
|
+
require 'reform/form/orm'
|
4
|
+
require 'reform/form/active_model'
|
3
5
|
require 'reform/form/active_model/validations'
|
6
|
+
require 'reform/form/active_model/model_reflections'
|
7
|
+
require 'reform/form/active_model/form_builder_methods'
|
4
8
|
module Valkyrie
|
5
9
|
##
|
6
10
|
# Standard change set object for Valkyrie.
|
@@ -16,7 +20,9 @@ module Valkyrie
|
|
16
20
|
class ChangeSet < Reform::Form
|
17
21
|
include Reform::Form::ORM
|
18
22
|
include Reform::Form::ModelReflections
|
23
|
+
include Reform::Form::ActiveModel
|
19
24
|
include Reform::Form::ActiveModel::Validations
|
25
|
+
include Reform::Form::ActiveModel::FormBuilderMethods
|
20
26
|
feature Coercion
|
21
27
|
class_attribute :fields
|
22
28
|
self.fields = []
|
@@ -62,6 +68,9 @@ module Valkyrie
|
|
62
68
|
fields
|
63
69
|
end
|
64
70
|
|
71
|
+
# Override reflect_on_association so SimpleForm can work.
|
72
|
+
def self.reflect_on_association(*_args); end
|
73
|
+
|
65
74
|
# Returns value for a given property.
|
66
75
|
# @param key [Symbol]
|
67
76
|
def [](key)
|
data/lib/valkyrie/persistence.rb
CHANGED
@@ -31,6 +31,7 @@ module Valkyrie
|
|
31
31
|
require 'valkyrie/persistence/composite_persister'
|
32
32
|
require 'valkyrie/persistence/delete_tracking_buffer'
|
33
33
|
require 'valkyrie/persistence/buffered_persister'
|
34
|
+
require 'valkyrie/persistence/shared'
|
34
35
|
autoload :Postgres, 'valkyrie/persistence/postgres'
|
35
36
|
autoload :Solr, 'valkyrie/persistence/solr'
|
36
37
|
autoload :Fedora, 'valkyrie/persistence/fedora'
|
@@ -201,8 +201,8 @@ module Valkyrie::Persistence::Fedora
|
|
201
201
|
end
|
202
202
|
|
203
203
|
def self.ordered?(value)
|
204
|
-
return false unless value.resource.class.
|
205
|
-
value.resource.
|
204
|
+
return false unless value.resource.class.attribute_names.include?(value.key)
|
205
|
+
value.resource.ordered_attribute?(value.key)
|
206
206
|
end
|
207
207
|
|
208
208
|
delegate :subject, to: :value
|
@@ -79,157 +79,7 @@ module Valkyrie::Persistence::Postgres
|
|
79
79
|
# Responsible for converting `metadata` JSON-B field in
|
80
80
|
# {Valkyrie::Persistence::Postgres::ORM::Resource} into an acceptable hash
|
81
81
|
# for {Valkyrie::Resource}
|
82
|
-
class RDFMetadata
|
83
|
-
attr_reader :metadata
|
84
|
-
|
85
|
-
# @param [Hash] metadata
|
86
|
-
def initialize(metadata)
|
87
|
-
# nil hash values are handled by the default state in dry-types
|
88
|
-
# anyways, so don't bother processing them here.
|
89
|
-
@metadata = metadata.compact
|
90
|
-
end
|
91
|
-
|
92
|
-
# Convert the database attribute values and map these to the existing keys in the Valkyrie Resource metadata
|
93
|
-
# @return [Hash]
|
94
|
-
def result
|
95
|
-
Hash[
|
96
|
-
metadata.map do |key, value|
|
97
|
-
[key, PostgresValue.for(value).result]
|
98
|
-
end
|
99
|
-
]
|
100
|
-
end
|
101
|
-
|
102
|
-
# Abstract base class for mapping PostgreSQL database field values to Valkyrie Resource attributes
|
103
|
-
class PostgresValue < ::Valkyrie::ValueMapper
|
104
|
-
end
|
105
|
-
|
106
|
-
# Converts {RDF::Literal} typed-literals from JSON-LD stored into an
|
107
|
-
# {RDF::Literal}
|
108
|
-
class HashValue < ::Valkyrie::ValueMapper
|
109
|
-
PostgresValue.register(self)
|
110
|
-
|
111
|
-
# Determines whether or not a value is a Hash containing the key "@value"
|
112
|
-
# @param [Object] value
|
113
|
-
# @return [Boolean]
|
114
|
-
def self.handles?(value)
|
115
|
-
value.is_a?(Hash) && value["@value"]
|
116
|
-
end
|
117
|
-
|
118
|
-
# Constructs a RDF::Literal object using the Object keyed to "@value"
|
119
|
-
# in the value Hash, as well as the language keyed to "@language" and
|
120
|
-
# datatype keyed to "@type"
|
121
|
-
# @return [RDF::Literal]
|
122
|
-
def result
|
123
|
-
RDF::Literal.new(value["@value"],
|
124
|
-
language: value["@language"],
|
125
|
-
datatype: value["@type"])
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
# Converts stored IDs into {Valkyrie::ID}s
|
130
|
-
class IDValue < ::Valkyrie::ValueMapper
|
131
|
-
PostgresValue.register(self)
|
132
|
-
|
133
|
-
# Determines whether or not a value is a Hash containing the key "id" (excluding those storing the Valkyrie Resource type)
|
134
|
-
# @param [Object] value
|
135
|
-
# @return [Boolean]
|
136
|
-
def self.handles?(value)
|
137
|
-
value.is_a?(Hash) && value["id"] && !value["internal_resource"]
|
138
|
-
end
|
139
|
-
|
140
|
-
# Constructs a Valkyrie::ID object using the String keyed to "id" in the value
|
141
|
-
# @return [Valkyrie::ID]
|
142
|
-
def result
|
143
|
-
Valkyrie::ID.new(value["id"])
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
# Converts stored URIs into {RDF::URI}s
|
148
|
-
class URIValue < ::Valkyrie::ValueMapper
|
149
|
-
PostgresValue.register(self)
|
150
|
-
|
151
|
-
# Determines whether or not a value is a Hash containing the key "@id"
|
152
|
-
# @param [Object] value
|
153
|
-
# @return [Boolean]
|
154
|
-
def self.handles?(value)
|
155
|
-
value.is_a?(Hash) && value["@id"]
|
156
|
-
end
|
157
|
-
|
158
|
-
# Constructs a RDF::URI object using the URI keyed to @id in the value
|
159
|
-
# @return [RDF::URI]
|
160
|
-
def result
|
161
|
-
::RDF::URI.new(value["@id"])
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# Converts nested records into {Valkyrie::Resource}s
|
166
|
-
class NestedRecord < ::Valkyrie::ValueMapper
|
167
|
-
PostgresValue.register(self)
|
168
|
-
|
169
|
-
# Determines whether or not a value is a Hash containing multiple keys
|
170
|
-
# @param [Object] value
|
171
|
-
# @return [Boolean]
|
172
|
-
def self.handles?(value)
|
173
|
-
value.is_a?(Hash) && value.keys.length > 1
|
174
|
-
end
|
175
|
-
|
176
|
-
# Generates a Hash derived from the RDFMetadata for the value
|
177
|
-
# @return [Hash]
|
178
|
-
def result
|
179
|
-
RDFMetadata.new(value).result.symbolize_keys
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
# Handles iterating over arrays of values and converting each value.
|
184
|
-
class EnumeratorValue < ::Valkyrie::ValueMapper
|
185
|
-
PostgresValue.register(self)
|
186
|
-
|
187
|
-
# Determines whether or not a value has enumerable behavior
|
188
|
-
# @param [Object] value
|
189
|
-
# @return [Boolean]
|
190
|
-
def self.handles?(value)
|
191
|
-
value.respond_to?(:each)
|
192
|
-
end
|
193
|
-
|
194
|
-
# Convert the elements in the enumerable value in Valkyrie attribute values
|
195
|
-
# Casts single-valued arrays to the first value, letting Types::Set and
|
196
|
-
# Types::Array handle converting it back.
|
197
|
-
# @return [Array<Object>]
|
198
|
-
def result
|
199
|
-
if value.length == 1
|
200
|
-
calling_mapper.for(value.first).result
|
201
|
-
else
|
202
|
-
value.map do |value|
|
203
|
-
calling_mapper.for(value).result
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
# Converts Date strings to `DateTime`
|
210
|
-
class DateValue < ::Valkyrie::ValueMapper
|
211
|
-
PostgresValue.register(self)
|
212
|
-
|
213
|
-
# Determines whether or not a value is an ISO 8601 datestamp String
|
214
|
-
# e. g. 1970-01-01
|
215
|
-
# @param [Object] value
|
216
|
-
# @return [Boolean]
|
217
|
-
def self.handles?(value)
|
218
|
-
return false unless value.is_a?(String)
|
219
|
-
return false unless value[4] == "-"
|
220
|
-
year = value.to_s[0..3]
|
221
|
-
return false unless year.length == 4 && year.to_i.to_s == year
|
222
|
-
DateTime.iso8601(value)
|
223
|
-
rescue
|
224
|
-
false
|
225
|
-
end
|
226
|
-
|
227
|
-
# Generates a Time object in the UTC from the datestamp string value
|
228
|
-
# @return [Time]
|
229
|
-
def result
|
230
|
-
DateTime.iso8601(value).utc
|
231
|
-
end
|
232
|
-
end
|
82
|
+
class RDFMetadata < ::Valkyrie::Persistence::Shared::JSONValueMapper
|
233
83
|
end
|
234
84
|
end
|
235
85
|
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Valkyrie::Persistence::Shared
|
3
|
+
# Converts a hash representation of a Resource back into a Resource.
|
4
|
+
# Often useful for converting back from JSON.
|
5
|
+
class JSONValueMapper
|
6
|
+
attr_reader :metadata
|
7
|
+
|
8
|
+
# @param [Hash] metadata
|
9
|
+
def initialize(metadata)
|
10
|
+
# nil hash values are handled by the default state in dry-types
|
11
|
+
# anyways, so don't bother processing them here.
|
12
|
+
@metadata = metadata.compact
|
13
|
+
end
|
14
|
+
|
15
|
+
# Convert the database attribute values and map these to the existing keys in the Valkyrie Resource metadata
|
16
|
+
# @return [Hash]
|
17
|
+
def result
|
18
|
+
Hash[
|
19
|
+
metadata.map do |key, value|
|
20
|
+
[key, PostgresValue.for(value).result]
|
21
|
+
end
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Abstract base class for mapping PostgreSQL database field values to Valkyrie Resource attributes
|
26
|
+
class PostgresValue < ::Valkyrie::ValueMapper
|
27
|
+
end
|
28
|
+
|
29
|
+
# Converts {RDF::Literal} typed-literals from JSON-LD stored into an
|
30
|
+
# {RDF::Literal}
|
31
|
+
class HashValue < ::Valkyrie::ValueMapper
|
32
|
+
PostgresValue.register(self)
|
33
|
+
|
34
|
+
# Determines whether or not a value is a Hash containing the key "@value"
|
35
|
+
# @param [Object] value
|
36
|
+
# @return [Boolean]
|
37
|
+
def self.handles?(value)
|
38
|
+
value.is_a?(Hash) && value["@value"]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Constructs a RDF::Literal object using the Object keyed to "@value"
|
42
|
+
# in the value Hash, as well as the language keyed to "@language" and
|
43
|
+
# datatype keyed to "@type"
|
44
|
+
# @return [RDF::Literal]
|
45
|
+
def result
|
46
|
+
RDF::Literal.new(value["@value"],
|
47
|
+
language: value["@language"],
|
48
|
+
datatype: value["@type"])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Converts stored IDs into {Valkyrie::ID}s
|
53
|
+
class IDValue < ::Valkyrie::ValueMapper
|
54
|
+
PostgresValue.register(self)
|
55
|
+
|
56
|
+
# Determines whether or not a value is a Hash containing the key "id" (excluding those storing the Valkyrie Resource type)
|
57
|
+
# @param [Object] value
|
58
|
+
# @return [Boolean]
|
59
|
+
def self.handles?(value)
|
60
|
+
value.is_a?(Hash) && value["id"] && !value["internal_resource"]
|
61
|
+
end
|
62
|
+
|
63
|
+
# Constructs a Valkyrie::ID object using the String keyed to "id" in the value
|
64
|
+
# @return [Valkyrie::ID]
|
65
|
+
def result
|
66
|
+
Valkyrie::ID.new(value["id"])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Converts stored URIs into {RDF::URI}s
|
71
|
+
class URIValue < ::Valkyrie::ValueMapper
|
72
|
+
PostgresValue.register(self)
|
73
|
+
|
74
|
+
# Determines whether or not a value is a Hash containing the key "@id"
|
75
|
+
# @param [Object] value
|
76
|
+
# @return [Boolean]
|
77
|
+
def self.handles?(value)
|
78
|
+
value.is_a?(Hash) && value["@id"]
|
79
|
+
end
|
80
|
+
|
81
|
+
# Constructs a RDF::URI object using the URI keyed to @id in the value
|
82
|
+
# @return [RDF::URI]
|
83
|
+
def result
|
84
|
+
::RDF::URI.new(value["@id"])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Converts nested records into {Valkyrie::Resource}s
|
89
|
+
class NestedRecord < ::Valkyrie::ValueMapper
|
90
|
+
PostgresValue.register(self)
|
91
|
+
|
92
|
+
# Determines whether or not a value is a Hash containing multiple keys
|
93
|
+
# @param [Object] value
|
94
|
+
# @return [Boolean]
|
95
|
+
def self.handles?(value)
|
96
|
+
value.is_a?(Hash) && value.keys.length > 1
|
97
|
+
end
|
98
|
+
|
99
|
+
# Generates a Hash derived from the JSON for the value
|
100
|
+
# @return [Hash]
|
101
|
+
def result
|
102
|
+
Valkyrie::Persistence::Shared::JSONValueMapper.new(value).result.symbolize_keys
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Handles iterating over arrays of values and converting each value.
|
107
|
+
class EnumeratorValue < ::Valkyrie::ValueMapper
|
108
|
+
PostgresValue.register(self)
|
109
|
+
|
110
|
+
# Determines whether or not a value has enumerable behavior
|
111
|
+
# @param [Object] value
|
112
|
+
# @return [Boolean]
|
113
|
+
def self.handles?(value)
|
114
|
+
value.respond_to?(:each)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Convert the elements in the enumerable value in Valkyrie attribute values
|
118
|
+
# Casts single-valued arrays to the first value, letting Types::Set and
|
119
|
+
# Types::Array handle converting it back.
|
120
|
+
# @return [Array<Object>]
|
121
|
+
def result
|
122
|
+
if value.length == 1
|
123
|
+
calling_mapper.for(value.first).result
|
124
|
+
else
|
125
|
+
value.map do |value|
|
126
|
+
calling_mapper.for(value).result
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Converts Date strings to `DateTime`
|
133
|
+
class DateValue < ::Valkyrie::ValueMapper
|
134
|
+
PostgresValue.register(self)
|
135
|
+
|
136
|
+
# Determines whether or not a value is an ISO 8601 datestamp String
|
137
|
+
# e. g. 1970-01-01
|
138
|
+
# @param [Object] value
|
139
|
+
# @return [Boolean]
|
140
|
+
def self.handles?(value)
|
141
|
+
return false unless value.is_a?(String)
|
142
|
+
return false unless value[4] == "-"
|
143
|
+
year = value.to_s[0..3]
|
144
|
+
return false unless year.length == 4 && year.to_i.to_s == year
|
145
|
+
DateTime.iso8601(value)
|
146
|
+
rescue
|
147
|
+
false
|
148
|
+
end
|
149
|
+
|
150
|
+
# Generates a Time object in the UTC from the datestamp string value
|
151
|
+
# @return [Time]
|
152
|
+
def result
|
153
|
+
DateTime.iso8601(value).utc
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/lib/valkyrie/resource.rb
CHANGED
@@ -19,15 +19,7 @@ module Valkyrie
|
|
19
19
|
# available key, and makes sure the defaults are set up if no value is
|
20
20
|
# given.
|
21
21
|
def self.allow_nonexistent_keys
|
22
|
-
|
23
|
-
transform_types do |type|
|
24
|
-
current_meta = type.meta.merge(omittable: true)
|
25
|
-
if type.default?
|
26
|
-
type.constructor(nil_2_undef).meta(current_meta)
|
27
|
-
else
|
28
|
-
type.meta(current_meta)
|
29
|
-
end
|
30
|
-
end
|
22
|
+
transform_types(&:omittable)
|
31
23
|
end
|
32
24
|
|
33
25
|
# Overridden to provide default attributes.
|
@@ -36,7 +28,7 @@ module Valkyrie
|
|
36
28
|
super(subclass)
|
37
29
|
subclass.allow_nonexistent_keys
|
38
30
|
subclass.attribute :id, Valkyrie::Types::ID.optional, internal: true
|
39
|
-
subclass.attribute :internal_resource, Valkyrie::Types::Any.default(subclass.to_s), internal: true
|
31
|
+
subclass.attribute :internal_resource, Valkyrie::Types::Any.default(subclass.to_s.freeze), internal: true
|
40
32
|
subclass.attribute :created_at, Valkyrie::Types::DateTime.optional, internal: true
|
41
33
|
subclass.attribute :updated_at, Valkyrie::Types::DateTime.optional, internal: true
|
42
34
|
subclass.attribute :new_record, Types::Bool.default(true), internal: true
|
@@ -44,7 +36,7 @@ module Valkyrie
|
|
44
36
|
|
45
37
|
# @return [Array<Symbol>] Array of fields defined for this class.
|
46
38
|
def self.fields
|
47
|
-
|
39
|
+
attribute_names.without(:new_record)
|
48
40
|
end
|
49
41
|
|
50
42
|
# Define an attribute. Attributes are used to describe resources.
|
@@ -53,7 +45,9 @@ module Valkyrie
|
|
53
45
|
# @note Overridden from {Dry::Struct} to make the default type
|
54
46
|
# {Valkyrie::Types::Set}
|
55
47
|
def self.attribute(name, type = Valkyrie::Types::Set.optional, internal: false)
|
56
|
-
raise ReservedAttributeError, "#{name} is a reserved attribute and defined by Valkyrie::Resource, do not redefine it." if reserved_attributes.include?(name.to_sym) &&
|
48
|
+
raise ReservedAttributeError, "#{name} is a reserved attribute and defined by Valkyrie::Resource, do not redefine it." if reserved_attributes.include?(name.to_sym) &&
|
49
|
+
attribute_names.include?(name.to_sym) &&
|
50
|
+
!internal
|
57
51
|
define_method("#{name}=") do |value|
|
58
52
|
set_value(name, value)
|
59
53
|
end
|
@@ -94,7 +88,11 @@ module Valkyrie
|
|
94
88
|
end
|
95
89
|
|
96
90
|
def attributes
|
97
|
-
super.
|
91
|
+
Hash[self.class.attribute_names.map { |x| [x, nil] }].merge(super).freeze
|
92
|
+
end
|
93
|
+
|
94
|
+
def __attributes__
|
95
|
+
Hash[@attributes].freeze
|
98
96
|
end
|
99
97
|
|
100
98
|
def dup
|
@@ -158,7 +156,12 @@ module Valkyrie
|
|
158
156
|
# @param key [#to_sym] the name of the attribute to set
|
159
157
|
# @param value [] the value to set key to.
|
160
158
|
def set_value(key, value)
|
161
|
-
@attributes[key.to_sym] = self.class.schema
|
159
|
+
@attributes[key.to_sym] = self.class.schema.key(key.to_sym).type.call(value)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns if an attribute is set as ordered.
|
163
|
+
def ordered_attribute?(key)
|
164
|
+
self.class.schema.key(key).type.meta.try(:[], :ordered)
|
162
165
|
end
|
163
166
|
|
164
167
|
class ReservedAttributeError < StandardError; end
|
@@ -76,7 +76,6 @@ RSpec.shared_examples 'a Valkyrie::Resource' do
|
|
76
76
|
resource.my_property = "test"
|
77
77
|
|
78
78
|
expect(resource[:my_property]).to eq ["test"]
|
79
|
-
resource_klass.schema.delete(:my_property)
|
80
79
|
end
|
81
80
|
it "returns nil for non-existent properties" do
|
82
81
|
resource = resource_klass.new
|
@@ -90,10 +89,17 @@ RSpec.shared_examples 'a Valkyrie::Resource' do
|
|
90
89
|
resource.other_property = "test"
|
91
90
|
|
92
91
|
expect(resource["other_property"]).to eq ["test"]
|
93
|
-
|
92
|
+
|
93
|
+
unset_key(resource_klass, :other_property)
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
+
def unset_key(resource_klass, property)
|
98
|
+
resource_klass.schema(Dry::Types::Schema.new(Hash, **resource_klass.schema.options, keys: resource_klass.schema.keys.select { |x| x.name != property }, meta: resource_klass.schema.meta))
|
99
|
+
resource_klass.instance_variable_set(:@attribute_names, nil)
|
100
|
+
resource_klass.allow_nonexistent_keys
|
101
|
+
end
|
102
|
+
|
97
103
|
describe "#set_value" do
|
98
104
|
it "can set a value" do
|
99
105
|
resource_klass.attribute :set_value_property unless resource_klass.schema.key?(:set_value_property)
|
@@ -104,7 +110,7 @@ RSpec.shared_examples 'a Valkyrie::Resource' do
|
|
104
110
|
expect(resource.set_value_property).to eq ["test"]
|
105
111
|
resource.set_value("set_value_property", "testing")
|
106
112
|
expect(resource.set_value_property).to eq ["testing"]
|
107
|
-
resource_klass
|
113
|
+
unset_key(resource_klass, :set_value_property)
|
108
114
|
end
|
109
115
|
end
|
110
116
|
|
@@ -115,14 +121,14 @@ RSpec.shared_examples 'a Valkyrie::Resource' do
|
|
115
121
|
resource = resource_klass.new(symbol_property: "bla")
|
116
122
|
|
117
123
|
expect(resource.symbol_property).to eq ["bla"]
|
118
|
-
resource_klass
|
124
|
+
unset_key(resource_klass, :symbol_property)
|
119
125
|
end
|
120
126
|
it "can not set values with string properties" do
|
121
127
|
resource_klass.attribute :string_property unless resource_klass.schema.key?(:string_property)
|
122
128
|
|
123
129
|
resource = nil
|
124
130
|
expect(resource).not_to respond_to :string_property
|
125
|
-
resource_klass
|
131
|
+
unset_key(resource_klass, :string_property)
|
126
132
|
end
|
127
133
|
end
|
128
134
|
|
@@ -137,7 +143,22 @@ RSpec.shared_examples 'a Valkyrie::Resource' do
|
|
137
143
|
expect(resource.attributes[:internal_resource]).to eq resource_klass.to_s
|
138
144
|
expect { resource.attributes.dup[:internal_resource] = "bla" }.not_to output.to_stderr
|
139
145
|
|
140
|
-
resource_klass
|
146
|
+
unset_key(resource_klass, :bla)
|
147
|
+
resource = resource_klass.new
|
148
|
+
expect(resource.attributes).not_to have_key(:bla)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#__attributes__" do
|
153
|
+
it "returns all defined attributes, but doesn't add nil keys" do
|
154
|
+
resource_klass.attribute :bla unless resource_klass.schema.key?(:bla)
|
155
|
+
|
156
|
+
resource = resource_klass.new
|
157
|
+
expect(resource.__attributes__).to be_frozen
|
158
|
+
expect(resource.__attributes__).not_to have_key :bla
|
159
|
+
expect(resource.__attributes__).to have_key :internal_resource
|
160
|
+
|
161
|
+
unset_key(resource_klass, :bla)
|
141
162
|
end
|
142
163
|
end
|
143
164
|
end
|
data/lib/valkyrie/types.rb
CHANGED
@@ -15,10 +15,10 @@ module Valkyrie
|
|
15
15
|
# @note Not all Dry::Types built-in types are supported in Valkyrie
|
16
16
|
# @see https://github.com/samvera-labs/valkyrie/wiki/Supported-Data-Types List of types supported in Valkyrie
|
17
17
|
module Types
|
18
|
-
include Dry
|
18
|
+
include Dry.Types(default: :nominal)
|
19
19
|
|
20
20
|
# Valkyrie::ID
|
21
|
-
ID = Dry::Types::
|
21
|
+
ID = Dry::Types::Nominal
|
22
22
|
.new(Valkyrie::ID)
|
23
23
|
.constructor do |input|
|
24
24
|
if input.respond_to?(:each)
|
@@ -40,7 +40,7 @@ module Valkyrie
|
|
40
40
|
end
|
41
41
|
|
42
42
|
# Valkyrie::URI
|
43
|
-
URI = Dry::Types::
|
43
|
+
URI = Dry::Types::Nominal
|
44
44
|
.new(RDF::URI)
|
45
45
|
.constructor do |input|
|
46
46
|
if input.present?
|
@@ -52,7 +52,7 @@ module Valkyrie
|
|
52
52
|
|
53
53
|
# Optimistic Lock Token
|
54
54
|
OptimisticLockToken =
|
55
|
-
Dry::Types::
|
55
|
+
Dry::Types::Nominal
|
56
56
|
.new(::Valkyrie::Persistence::OptimisticLockToken)
|
57
57
|
.constructor do |input|
|
58
58
|
Valkyrie::Persistence::OptimisticLockToken.deserialize(input)
|
@@ -96,13 +96,6 @@ module Valkyrie
|
|
96
96
|
def of(type)
|
97
97
|
super.default([].freeze)
|
98
98
|
end
|
99
|
-
|
100
|
-
# Override optional to provide a default because without it an
|
101
|
-
# instantiated Valkyrie::Resource's internal hash does not have values for
|
102
|
-
# every possible attribute, resulting in `MissingAttributeError`.
|
103
|
-
def optional
|
104
|
-
super.default(nil)
|
105
|
-
end
|
106
99
|
end
|
107
100
|
Array.singleton_class.include(ArrayDefault)
|
108
101
|
Set.singleton_class.include(ArrayDefault)
|
data/lib/valkyrie/version.rb
CHANGED
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', '~> 1.0'
|
26
26
|
spec.add_dependency 'rdf'
|
27
27
|
spec.add_dependency 'activesupport'
|
28
28
|
spec.add_dependency 'railties' # To use generators and engines
|
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_dependency 'json-ld'
|
32
32
|
spec.add_dependency 'json'
|
33
33
|
spec.add_dependency 'rdf-vocab'
|
34
|
+
spec.add_dependency 'disposable', '~> 0.4.5'
|
34
35
|
|
35
36
|
spec.add_development_dependency "bundler", "~> 1.16"
|
36
37
|
spec.add_development_dependency "rake", "~> 10.0"
|
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: 2.0.0.
|
4
|
+
version: 2.0.0.RC6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Trey Pendragon
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-struct
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '1.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: '1.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rdf
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,6 +178,20 @@ dependencies:
|
|
178
178
|
- - ">="
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: disposable
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: 0.4.5
|
188
|
+
type: :runtime
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: 0.4.5
|
181
195
|
- !ruby/object:Gem::Dependency
|
182
196
|
name: bundler
|
183
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -474,6 +488,8 @@ files:
|
|
474
488
|
- lib/valkyrie/persistence/postgres/query_service.rb
|
475
489
|
- lib/valkyrie/persistence/postgres/resource_converter.rb
|
476
490
|
- lib/valkyrie/persistence/postgres/resource_factory.rb
|
491
|
+
- lib/valkyrie/persistence/shared.rb
|
492
|
+
- lib/valkyrie/persistence/shared/json_value_mapper.rb
|
477
493
|
- lib/valkyrie/persistence/solr.rb
|
478
494
|
- lib/valkyrie/persistence/solr/composite_indexer.rb
|
479
495
|
- lib/valkyrie/persistence/solr/metadata_adapter.rb
|