valkyrie 2.0.0.RC5 → 2.0.0.RC6
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 +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: [](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
|