valkyrie-sequel 1.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d6e9fe995f047640837186d5468d2c13c1a4bde5
4
- data.tar.gz: 2802d8cdee2d9bc7a029be53053a8d2df0e56358
2
+ SHA256:
3
+ metadata.gz: cd54c1445fecd7ace70e07607d27da780bf9c47d6ac97c8681ab319908e1c36b
4
+ data.tar.gz: bce2c0e04e1c6aae88d0dfae9bcbb35fc0a4055c2223284526165fb71a34adde
5
5
  SHA512:
6
- metadata.gz: bb9d0289ef5b574b75447c06531416f306db195ad9a3e213cba51ab4671bd3cf62504a107f5647f6a6f2262b45805d832ad88bfbbf5252d3b953d2a2963dd743
7
- data.tar.gz: 9d38118312e0e27e71c8035b40eabc23c15719bbe33b87d4deb2e99fc1347f95384e457ee1480ebbab71d6072eff3750281dc96b8a8fc933ca6639365da27c13
6
+ metadata.gz: e7b5a2524a6c10a7b49757ceb360560f2aac259c7376ff0abe51c456eaa8750b4dfdc9185dd692b1041a04bfaa649a047b240427ac4bc5be802fd7de4ebbff05
7
+ data.tar.gz: 789f2e2931f1c8ea9552124e1119a9582e2c703261782b1f4d242191391f01f5725994c70bb8d4653f5525b60bd8d0d7221177116eacde9862b05aa2e6ecc4a3
data/.circleci/config.yml CHANGED
@@ -3,9 +3,10 @@ version: 2
3
3
  jobs:
4
4
  build:
5
5
  docker:
6
- - image: circleci/ruby:2.3.7-node-browsers
6
+ - image: circleci/ruby:2.7.2-node-browsers
7
7
  environment:
8
8
  RAILS_ENV: test
9
+ BUNDLE_PATH: vendor/bundle
9
10
  DB_HOST: localhost
10
11
  DB_USERNAME: valkyrie_sequel
11
12
  DB_PASSWORD: ""
@@ -21,8 +22,9 @@ jobs:
21
22
  - type: cache-restore
22
23
  name: Restore bundle cache
23
24
  key: valkyrie-sequel-{{ checksum "Gemfile" }}
25
+ - run: gem install bundler -v '~> 2.0'
24
26
  # Bundle install dependencies
25
- - run: bundle install --path vendor/bundle
27
+ - run: bundle install
26
28
  # Cache Dependencies
27
29
  - type: cache-save
28
30
  name: Store bundle cache
data/.rubocop.yml CHANGED
@@ -2,7 +2,6 @@ inherit_gem:
2
2
  bixby: bixby_default.yml
3
3
  AllCops:
4
4
  DisplayCopNames: true
5
- TargetRubyVersion: 2.3
6
5
  Exclude:
7
6
  - 'bin/*'
8
7
  - 'db/schema.rb'
@@ -14,6 +13,7 @@ Naming/FileName:
14
13
  Metrics/BlockLength:
15
14
  Exclude:
16
15
  - 'spec/**/*.rb'
16
+ - 'valkyrie-sequel.gemspec'
17
17
  Metrics/ClassLength:
18
18
  Exclude:
19
19
  - 'lib/valkyrie/sequel/query_service.rb'
@@ -23,3 +23,5 @@ Metrics/ParameterLists:
23
23
  RSpec/ExampleLength:
24
24
  Exclude:
25
25
  - 'spec/valkyrie/sequel/persister_spec.rb'
26
+ Rails/RakeEnvironment:
27
+ Enabled: false
@@ -48,16 +48,16 @@ module Valkyrie::Sequel
48
48
 
49
49
  private
50
50
 
51
- def host
52
- connection.opts[:host]
53
- end
51
+ def host
52
+ connection.opts[:host]
53
+ end
54
54
 
55
- def port
56
- connection.opts[:port]
57
- end
55
+ def port
56
+ connection.opts[:port]
57
+ end
58
58
 
59
- def database
60
- connection.opts[:database]
61
- end
59
+ def database
60
+ connection.opts[:database]
61
+ end
62
62
  end
63
63
  end
@@ -121,32 +121,32 @@ module Valkyrie::Sequel
121
121
 
122
122
  private
123
123
 
124
- def create_or_update(resource:, attributes:)
125
- attributes[:updated_at] = Time.now.utc
126
- attributes[:created_at] ||= Time.now.utc
127
- return create(resource: resource, attributes: attributes) unless resource.persisted? && !exists?(id: attributes[:id])
128
- update(resource: resource, attributes: attributes)
129
- end
124
+ def create_or_update(resource:, attributes:)
125
+ attributes[:updated_at] = Time.now.utc
126
+ attributes[:created_at] ||= Time.now.utc
127
+ return create(resource: resource, attributes: attributes) unless resource.persisted? && !exists?(id: attributes[:id])
128
+ update(resource: resource, attributes: attributes)
129
+ end
130
130
 
131
- def create(resource:, attributes:)
132
- attributes[:lock_version] = 0 if resource.optimistic_locking_enabled? && resources.columns.include?(:lock_version)
133
- Array(resources.returning.insert(attributes)).first
134
- end
131
+ def create(resource:, attributes:)
132
+ attributes[:lock_version] = 0 if resource.optimistic_locking_enabled? && resources.columns.include?(:lock_version)
133
+ Array(resources.returning.insert(attributes)).first
134
+ end
135
135
 
136
- def update(resource:, attributes:)
137
- relation = resources.where(id: attributes[:id])
138
- if resource.optimistic_locking_enabled?
139
- relation = relation.where(Sequel.function(:coalesce, :lock_version, 0) => attributes[:lock_version] || 0)
140
- attributes[:lock_version] = (Sequel.function(:coalesce, :lock_version, 0) + 1)
141
- end
142
- attributes.delete(:lock_version) if attributes[:lock_version].nil?
143
- output = relation.returning.update(attributes)
144
- raise Valkyrie::Persistence::StaleObjectError, "The object #{resource.id} has been updated by another process." if output.blank? && resource.optimistic_locking_enabled?
145
- Array(output).first
136
+ def update(resource:, attributes:)
137
+ relation = resources.where(id: attributes[:id])
138
+ if resource.optimistic_locking_enabled?
139
+ relation = relation.where(Sequel.function(:coalesce, :lock_version, 0) => attributes[:lock_version] || 0)
140
+ attributes[:lock_version] = (Sequel.function(:coalesce, :lock_version, 0) + 1)
146
141
  end
142
+ attributes.delete(:lock_version) if attributes[:lock_version].nil?
143
+ output = relation.returning.update(attributes)
144
+ raise Valkyrie::Persistence::StaleObjectError, "The object #{resource.id} has been updated by another process." if output.blank? && resource.optimistic_locking_enabled?
145
+ Array(output).first
146
+ end
147
147
 
148
- def exists?(id:)
149
- resources.select(1).first(id: id).nil?
150
- end
148
+ def exists?(id:)
149
+ resources.select(1).first(id: id).nil?
150
+ end
151
151
  end
152
152
  end
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Sequel
3
3
  class QueryService
4
- ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
4
+ # ACCEPTABLE_UUID is deprecated and unused.
5
+ # which IDs are acceptable is now decided by the database.
6
+ ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}.freeze
7
+ DEFAULT_ID_TYPE = :uuid
8
+
5
9
  attr_reader :adapter
6
10
  delegate :resources, :resource_factory, :connection, to: :adapter
7
11
  def initialize(adapter:)
@@ -14,14 +18,27 @@ module Valkyrie::Sequel
14
18
  end
15
19
  end
16
20
 
21
+ # rubocop:disable Metrics/MethodLength
17
22
  def find_by(id:)
18
23
  id = Valkyrie::ID.new(id.to_s) if id.is_a?(String)
19
24
  validate_id(id)
20
- raise Valkyrie::Persistence::ObjectNotFoundError unless ACCEPTABLE_UUID.match?(id.to_s)
21
- attributes = resources.first(id: id.to_s)
25
+ attributes = nil
26
+ # Create a nested transaction so it can rollback to a non-essential
27
+ # savepoint if the query fails, not wrecking upstream transactions.
28
+ connection.transaction(savepoint: true) do
29
+ attributes = resources.first(id: id.to_s)
30
+ end
22
31
  raise Valkyrie::Persistence::ObjectNotFoundError unless attributes
23
32
  resource_factory.to_resource(object: attributes)
33
+ rescue Sequel::DatabaseError => err
34
+ case err.cause
35
+ when PG::InvalidTextRepresentation
36
+ raise Valkyrie::Persistence::ObjectNotFoundError
37
+ else
38
+ raise err
39
+ end
24
40
  end
41
+ # rubocop:enable Metrics/MethodLength
25
42
 
26
43
  def find_all_of_model(model:)
27
44
  resources.where(internal_resource: model.to_s).map do |attributes|
@@ -29,37 +46,45 @@ module Valkyrie::Sequel
29
46
  end
30
47
  end
31
48
 
49
+ # Count all records for a specific resource type
50
+ # @param [Class] model
51
+ # @return integer
52
+ def count_all_of_model(model:)
53
+ resources.where(internal_resource: model.to_s).count
54
+ end
55
+
32
56
  def find_many_by_ids(ids:)
33
57
  ids = ids.map do |id|
34
58
  id = Valkyrie::ID.new(id.to_s) if id.is_a?(String)
35
59
  validate_id(id)
36
60
  id.to_s
37
61
  end
38
- ids = ids.select do |id|
39
- ACCEPTABLE_UUID.match?(id)
40
- end
41
62
 
42
- resources.where(id: ids).map do |attributes|
63
+ resources.where(Sequel.lit('(id::varchar) IN ?', ids)).map do |attributes|
43
64
  resource_factory.to_resource(object: attributes)
44
65
  end
45
66
  end
46
67
 
47
- def find_references_by(resource:, property:)
68
+ def find_references_by(resource:, property:, model: nil)
48
69
  return [] if resource.id.blank? || resource[property].blank?
49
70
  # only return ordered if needed to avoid performance penalties
50
71
  if ordered_property?(resource: resource, property: property)
51
- run_query(find_ordered_references_query, property.to_s, resource.id.to_s)
72
+ find_ordered_references_by(resource: resource, property: property, model: model)
52
73
  else
53
- run_query(find_references_query, property.to_s, resource.id.to_s)
74
+ find_unordered_references_by(resource: resource, property: property, model: model)
54
75
  end
55
76
  end
56
77
 
57
- def find_inverse_references_by(resource: nil, id: nil, property:)
78
+ def find_inverse_references_by(resource: nil, id: nil, model: nil, property:)
58
79
  raise ArgumentError, "Provide resource or id" unless resource || id
59
80
  ensure_persisted(resource) if resource
60
81
  id ||= resource.id
61
82
  internal_array = { property => [id: id.to_s] }
62
- run_query(find_inverse_references_query, internal_array.to_json)
83
+ if model
84
+ run_query(find_inverse_references_with_model_query, internal_array.to_json, model.to_s)
85
+ else
86
+ run_query(find_inverse_references_query, internal_array.to_json)
87
+ end
63
88
  end
64
89
 
65
90
  # Find and a record using a Valkyrie ID for an alternate ID, and construct
@@ -100,106 +125,149 @@ module Valkyrie::Sequel
100
125
 
101
126
  private
102
127
 
103
- # Generate the SQL query for retrieving member resources in PostgreSQL using a
104
- # resource ID as an argument.
105
- # @see https://guides.rubyonrails.org/active_record_querying.html#array-conditions
106
- # @note this uses a CROSS JOIN for all combinations of member IDs with the
107
- # IDs of their parents
108
- # @see https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-FROM
109
- # This also uses JSON functions in order to retrieve JSON property values
110
- # @see https://www.postgresql.org/docs/current/static/functions-json.html
111
- # @return [String]
112
- def find_members_query
113
- <<-SQL
128
+ # Generate the SQL query for retrieving member resources in PostgreSQL using a
129
+ # resource ID as an argument.
130
+ # @see https://guides.rubyonrails.org/active_record_querying.html#array-conditions
131
+ # @note this uses a CROSS JOIN for all combinations of member IDs with the
132
+ # IDs of their parents
133
+ # @see https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-FROM
134
+ # This also uses JSON functions in order to retrieve JSON property values
135
+ # @see https://www.postgresql.org/docs/current/static/functions-json.html
136
+ # @return [String]
137
+ def find_members_query
138
+ <<-SQL
114
139
  SELECT member.* FROM orm_resources a,
115
140
  jsonb_array_elements(a.metadata->'member_ids') WITH ORDINALITY AS b(member, member_pos)
116
141
  JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = ?
117
142
  ORDER BY b.member_pos
118
143
  SQL
119
- end
144
+ end
120
145
 
121
- # Generate the SQL query for retrieving member resources in PostgreSQL using a
122
- # resource ID and resource type as arguments.
123
- # @see https://guides.rubyonrails.org/active_record_querying.html#array-conditions
124
- # @note this uses a CROSS JOIN for all combinations of member IDs with the
125
- # IDs of their parents
126
- # @see https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-FROM
127
- # This also uses JSON functions in order to retrieve JSON property values
128
- # @see https://www.postgresql.org/docs/current/static/functions-json.html
129
- # @return [String]
130
- def find_members_with_type_query
131
- <<-SQL
146
+ # Generate the SQL query for retrieving member resources in PostgreSQL using a
147
+ # resource ID and resource type as arguments.
148
+ # @see https://guides.rubyonrails.org/active_record_querying.html#array-conditions
149
+ # @note this uses a CROSS JOIN for all combinations of member IDs with the
150
+ # IDs of their parents
151
+ # @see https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-FROM
152
+ # This also uses JSON functions in order to retrieve JSON property values
153
+ # @see https://www.postgresql.org/docs/current/static/functions-json.html
154
+ # @return [String]
155
+ def find_members_with_type_query
156
+ <<-SQL
132
157
  SELECT member.* FROM orm_resources a,
133
158
  jsonb_array_elements(a.metadata->'member_ids') WITH ORDINALITY AS b(member, member_pos)
134
159
  JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = ?
135
160
  AND member.internal_resource = ?
136
161
  ORDER BY b.member_pos
137
162
  SQL
138
- end
163
+ end
139
164
 
140
- # Generate the SQL query for retrieving member resources in PostgreSQL using a
141
- # JSON object literal as an argument (e. g. { "alternate_ids": [{"id": "d6e88f80-41b3-4dbf-a2a0-cd79e20f6d10"}] }).
142
- # @see https://guides.rubyonrails.org/active_record_querying.html#array-conditions
143
- # This uses JSON functions in order to retrieve JSON property values
144
- # @see https://www.postgresql.org/docs/current/static/functions-json.html
145
- # @return [String]
146
- def find_inverse_references_query
147
- <<-SQL
165
+ # Generate the SQL query for retrieving member resources in PostgreSQL using a
166
+ # JSON object literal as an argument (e. g. { "alternate_ids": [{"id": "d6e88f80-41b3-4dbf-a2a0-cd79e20f6d10"}] }).
167
+ # @see https://guides.rubyonrails.org/active_record_querying.html#array-conditions
168
+ # This uses JSON functions in order to retrieve JSON property values
169
+ # @see https://www.postgresql.org/docs/current/static/functions-json.html
170
+ # @return [String]
171
+ def find_inverse_references_query
172
+ <<-SQL
148
173
  SELECT * FROM orm_resources WHERE
149
174
  metadata @> ?
150
175
  SQL
151
- end
176
+ end
177
+
178
+ def find_inverse_references_with_model_query
179
+ <<-SQL
180
+ SELECT * FROM orm_resources WHERE
181
+ metadata @> ?
182
+ AND internal_resource = ?
183
+ SQL
184
+ end
152
185
 
153
- # Generate the SQL query for retrieving member resources in PostgreSQL using a
154
- # JSON object literal and resource ID as arguments.
155
- # @see https://guides.rubyonrails.org/active_record_querying.html#array-conditions
156
- # @note this uses a CROSS JOIN for all combinations of member IDs with the
157
- # IDs of their parents
158
- # @see https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-FROM
159
- # This also uses JSON functions in order to retrieve JSON property values
160
- # @see https://www.postgresql.org/docs/current/static/functions-json.html
161
- # @return [String]
162
- def find_references_query
163
- <<-SQL
186
+ # Generate the SQL query for retrieving member resources in PostgreSQL using a
187
+ # JSON object literal and resource ID as arguments.
188
+ # @see https://guides.rubyonrails.org/active_record_querying.html#array-conditions
189
+ # @note this uses a CROSS JOIN for all combinations of member IDs with the
190
+ # IDs of their parents
191
+ # @see https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-FROM
192
+ # This also uses JSON functions in order to retrieve JSON property values
193
+ # @see https://www.postgresql.org/docs/current/static/functions-json.html
194
+ # @return [String]
195
+ def find_references_query
196
+ <<-SQL
164
197
  SELECT DISTINCT member.* FROM orm_resources a,
165
198
  jsonb_array_elements(a.metadata->?) AS b(member)
166
199
  JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = ?
167
200
  SQL
168
- end
201
+ end
202
+
203
+ def find_references_with_type_query
204
+ <<-SQL
205
+ SELECT DISTINCT member.* FROM orm_resources a,
206
+ jsonb_array_elements(a.metadata->?) AS b(member)
207
+ JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = ?
208
+ AND member.internal_resource = ?
209
+ SQL
210
+ end
169
211
 
170
- def find_ordered_references_query
171
- <<-SQL
212
+ def find_ordered_references_query
213
+ <<-SQL
172
214
  SELECT member.* FROM orm_resources a,
173
215
  jsonb_array_elements(a.metadata->?) WITH ORDINALITY AS b(member, member_pos)
174
216
  JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = ?
175
217
  ORDER BY b.member_pos
176
218
  SQL
177
- end
219
+ end
178
220
 
179
- # Accesses the data type in PostgreSQL used for the primary key
180
- # (For example, a UUID)
181
- # @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaCache.html#method-i-columns_hash
182
- # @return [Symbol]
183
- def id_type
184
- @id_type ||= :uuid
185
- end
221
+ def find_ordered_references_with_type_query
222
+ <<-SQL
223
+ SELECT member.* FROM orm_resources a,
224
+ jsonb_array_elements(a.metadata->?) WITH ORDINALITY AS b(member, member_pos)
225
+ JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = ?
226
+ AND member.internal_resource = ?
227
+ ORDER BY b.member_pos
228
+ SQL
229
+ end
186
230
 
187
- # Determines whether or not an Object is a Valkyrie ID
188
- # @param [Object] id
189
- # @raise [ArgumentError]
190
- def validate_id(id)
191
- raise ArgumentError, 'id must be a Valkyrie::ID' unless id.is_a? Valkyrie::ID
192
- end
231
+ # Accesses the data type in PostgreSQL used for the primary key
232
+ # (For example, a UUID)
233
+ # @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaCache.html#method-i-columns_hash
234
+ # @return [Symbol]
235
+ def id_type
236
+ @id_type ||= DEFAULT_ID_TYPE
237
+ end
193
238
 
194
- # Determines whether or not a resource has been persisted
195
- # @param [Object] resource
196
- # @raise [ArgumentError]
197
- def ensure_persisted(resource)
198
- raise ArgumentError, 'resource is not saved' unless resource.persisted?
239
+ # Determines whether or not an Object is a Valkyrie ID
240
+ # @param [Object] id
241
+ # @raise [ArgumentError]
242
+ def validate_id(id)
243
+ raise ArgumentError, 'id must be a Valkyrie::ID' unless id.is_a? Valkyrie::ID
244
+ end
245
+
246
+ # Determines whether or not a resource has been persisted
247
+ # @param [Object] resource
248
+ # @raise [ArgumentError]
249
+ def ensure_persisted(resource)
250
+ raise ArgumentError, 'resource is not saved' unless resource.persisted?
251
+ end
252
+
253
+ def ordered_property?(resource:, property:)
254
+ resource.ordered_attribute?(property)
255
+ end
256
+
257
+ def find_ordered_references_by(resource:, property:, model: nil)
258
+ if model
259
+ run_query(find_ordered_references_with_type_query, property.to_s, resource.id.to_s, model.to_s)
260
+ else
261
+ run_query(find_ordered_references_query, property.to_s, resource.id.to_s)
199
262
  end
263
+ end
200
264
 
201
- def ordered_property?(resource:, property:)
202
- resource.class.schema[property].meta.try(:[], :ordered)
265
+ def find_unordered_references_by(resource:, property:, model: nil)
266
+ if model
267
+ run_query(find_references_with_type_query, property.to_s, resource.id.to_s, model.to_s)
268
+ else
269
+ run_query(find_references_query, property.to_s, resource.id.to_s)
203
270
  end
271
+ end
204
272
  end
205
273
  end
@@ -13,48 +13,48 @@ module Valkyrie::Sequel
13
13
 
14
14
  private
15
15
 
16
- # Construct a new Valkyrie Resource using the attributes retrieved from the database
17
- # @return [Valkyrie::Resource]
18
- def resource
19
- resource_klass.new(
20
- attributes.merge(
21
- new_record: false,
22
- Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK => lock_token
23
- )
16
+ # Construct a new Valkyrie Resource using the attributes retrieved from the database
17
+ # @return [Valkyrie::Resource]
18
+ def resource
19
+ resource_klass.new(
20
+ attributes.merge(
21
+ new_record: false,
22
+ Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK => lock_token
24
23
  )
25
- end
26
-
27
- # Construct the optimistic lock token using the adapter and lock version for the Resource
28
- # @return [Valkyrie::Persistence::OptimisticLockToken]
29
- def lock_token
30
- return nil unless object[:lock_version].present?
31
- @lock_token ||=
32
- Valkyrie::Persistence::OptimisticLockToken.new(
33
- adapter_id: resource_factory.adapter_id,
34
- token: object[:lock_version]
35
- )
36
- end
37
-
38
- # Retrieve the Class used to construct the Valkyrie Resource
39
- # @return [Class]
40
- def resource_klass
41
- internal_resource.constantize
42
- end
43
-
44
- # Access the String for the Valkyrie Resource type within the attributes
45
- # @return [String]
46
- def internal_resource
47
- attributes[:internal_resource]
48
- end
49
-
50
- def attributes
51
- @attributes ||= object.except(:metadata).merge(rdf_metadata).symbolize_keys
52
- end
53
-
54
- # Generate a Hash derived from Valkyrie Resource metadata encoded in the RDF
55
- # @return [Hash]
56
- def rdf_metadata
57
- @rdf_metadata ||= Valkyrie::Persistence::Postgres::ORMConverter::RDFMetadata.new(object[:metadata]).result
58
- end
24
+ )
25
+ end
26
+
27
+ # Construct the optimistic lock token using the adapter and lock version for the Resource
28
+ # @return [Valkyrie::Persistence::OptimisticLockToken]
29
+ def lock_token
30
+ return nil if object[:lock_version].blank?
31
+ @lock_token ||=
32
+ Valkyrie::Persistence::OptimisticLockToken.new(
33
+ adapter_id: resource_factory.adapter_id,
34
+ token: object[:lock_version]
35
+ )
36
+ end
37
+
38
+ # Retrieve the Class used to construct the Valkyrie Resource
39
+ # @return [Class]
40
+ def resource_klass
41
+ internal_resource.constantize
42
+ end
43
+
44
+ # Access the String for the Valkyrie Resource type within the attributes
45
+ # @return [String]
46
+ def internal_resource
47
+ attributes[:internal_resource]
48
+ end
49
+
50
+ def attributes
51
+ @attributes ||= object.except(:metadata).merge(rdf_metadata).symbolize_keys
52
+ end
53
+
54
+ # Generate a Hash derived from Valkyrie Resource metadata encoded in the RDF
55
+ # @return [Hash]
56
+ def rdf_metadata
57
+ @rdf_metadata ||= Valkyrie::Persistence::Shared::JSONValueMapper.new(object[:metadata]).result
58
+ end
59
59
  end
60
60
  end
@@ -1,6 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Sequel
3
3
  class ResourceFactory::ResourceConverter
4
+ PRIMARY_TERMS = [
5
+ :id,
6
+ :created_at,
7
+ :updated_at,
8
+ :internal_resource
9
+ ].freeze
10
+
11
+ DISALLOWED_TERMS = [
12
+ :new_record
13
+ ].freeze
14
+
4
15
  attr_reader :resource, :resource_factory
5
16
  delegate :orm_class, :adapter, to: :resource_factory
6
17
  delegate :resources, to: :adapter
@@ -12,68 +23,52 @@ module Valkyrie::Sequel
12
23
  def convert!
13
24
  output = database_hash
14
25
  output[:id] = resource.id.to_s if resource.id
15
- output.delete(:id) unless !output[:id] || QueryService::ACCEPTABLE_UUID.match?(output[:id].to_s)
16
26
  process_lock_token(output)
17
27
  output
18
28
  end
19
29
 
20
30
  private
21
31
 
22
- # Retrieves the optimistic lock token from the Valkyrie attribute value and
23
- # sets it to the lock_version on ORM resource
24
- # @see https://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
25
- # @param [ORM::Resource] orm_object
26
- def process_lock_token(orm_object)
27
- return unless resource.respond_to?(Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK)
28
- postgres_token = (resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK] || []).find do |token|
29
- token.adapter_id == resource_factory.adapter_id
30
- end
31
- return unless postgres_token
32
- orm_object[:lock_version] = postgres_token.token
33
- end
34
-
35
- def database_hash
36
- resource_hash.select do |k, _v|
37
- primary_terms.include?(k)
38
- end.compact.merge(
39
- metadata: ::Sequel.pg_json(metadata_hash)
40
- )
32
+ # Retrieves the optimistic lock token from the Valkyrie attribute value and
33
+ # sets it to the lock_version on ORM resource
34
+ # @see https://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
35
+ # @param [ORM::Resource] orm_object
36
+ def process_lock_token(orm_object)
37
+ return unless resource.respond_to?(Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK)
38
+ postgres_token = (resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK] || []).find do |token|
39
+ token.adapter_id == resource_factory.adapter_id
41
40
  end
41
+ return unless postgres_token
42
+ orm_object[:lock_version] = postgres_token.token
43
+ end
42
44
 
43
- def resource_hash
44
- @resource_hash ||= resource.to_h
45
- end
45
+ def database_hash
46
+ resource_hash.select do |k, _v|
47
+ PRIMARY_TERMS.include?(k)
48
+ end.compact.merge(
49
+ metadata: ::Sequel.pg_json(metadata_hash)
50
+ )
51
+ end
46
52
 
47
- # Convert attributes to all be arrays to better enable querying and
48
- # "changing of minds" later on.
49
- # @return [Hash]
50
- def metadata_hash
51
- Hash[
52
- selected_resource_attributes.compact.map do |k, v|
53
- [k, Array.wrap(v)]
54
- end
55
- ]
56
- end
53
+ def resource_hash
54
+ @resource_hash ||= resource.__attributes__
55
+ end
57
56
 
58
- def selected_resource_attributes
59
- resource_hash.select do |k, _v|
60
- !primary_terms.include?(k) && !blacklist_terms.include?(k)
57
+ # Convert attributes to all be arrays to better enable querying and
58
+ # "changing of minds" later on.
59
+ # @return [Hash]
60
+ def metadata_hash
61
+ Hash[
62
+ selected_resource_attributes.compact.map do |k, v|
63
+ [k, Array.wrap(v)]
61
64
  end
62
- end
63
-
64
- def primary_terms
65
- [
66
- :id,
67
- :created_at,
68
- :updated_at,
69
- :internal_resource
70
- ]
71
- end
65
+ ]
66
+ end
72
67
 
73
- def blacklist_terms
74
- [
75
- :new_record
76
- ]
68
+ def selected_resource_attributes
69
+ resource_hash.select do |k, _v|
70
+ !PRIMARY_TERMS.include?(k) && !DISALLOWED_TERMS.include?(k)
77
71
  end
72
+ end
78
73
  end
79
74
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie
3
3
  module Sequel
4
- VERSION = "1.1.0"
4
+ VERSION = "2.2.0"
5
5
  end
6
6
  end
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
  lib = File.expand_path("../lib", __FILE__)
4
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -21,16 +20,15 @@ Gem::Specification.new do |spec|
21
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
21
  spec.require_paths = ["lib"]
23
22
 
24
- spec.add_dependency "sequel"
25
- spec.add_dependency "sequel_pg"
26
- spec.add_dependency "valkyrie", '>= 1.5.0', '< 3.0.0'
27
- spec.add_dependency "oj"
28
- spec.add_development_dependency "bundler", "~> 1.16"
29
- spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_dependency "sequel", "~> 5.0"
24
+ spec.add_dependency "sequel_pg", "~> 1.0"
25
+ spec.add_dependency "valkyrie", '~> 2.1.0'
26
+ spec.add_dependency "oj", "~> 3.0"
27
+ spec.add_development_dependency "bundler", "~> 2.0"
28
+ spec.add_development_dependency "rake"
30
29
  spec.add_development_dependency "rspec", "~> 3.0"
31
30
  spec.add_development_dependency "bixby"
32
31
  spec.add_development_dependency "pry-byebug"
33
- spec.add_development_dependency "database_cleaner"
34
- spec.add_development_dependency "coveralls"
32
+ spec.add_development_dependency "database_cleaner", "< 2"
35
33
  spec.add_development_dependency "simplecov"
36
34
  end
metadata CHANGED
@@ -1,105 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valkyrie-sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Trey Pendragon
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-04-18 00:00:00.000000000 Z
11
+ date: 2021-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '5.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '5.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sequel_pg
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: valkyrie
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: 1.5.0
48
- - - "<"
45
+ - - "~>"
49
46
  - !ruby/object:Gem::Version
50
- version: 3.0.0
47
+ version: 2.1.0
51
48
  type: :runtime
52
49
  prerelease: false
53
50
  version_requirements: !ruby/object:Gem::Requirement
54
51
  requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: 1.5.0
58
- - - "<"
52
+ - - "~>"
59
53
  - !ruby/object:Gem::Version
60
- version: 3.0.0
54
+ version: 2.1.0
61
55
  - !ruby/object:Gem::Dependency
62
56
  name: oj
63
57
  requirement: !ruby/object:Gem::Requirement
64
58
  requirements:
65
- - - ">="
59
+ - - "~>"
66
60
  - !ruby/object:Gem::Version
67
- version: '0'
61
+ version: '3.0'
68
62
  type: :runtime
69
63
  prerelease: false
70
64
  version_requirements: !ruby/object:Gem::Requirement
71
65
  requirements:
72
- - - ">="
66
+ - - "~>"
73
67
  - !ruby/object:Gem::Version
74
- version: '0'
68
+ version: '3.0'
75
69
  - !ruby/object:Gem::Dependency
76
70
  name: bundler
77
71
  requirement: !ruby/object:Gem::Requirement
78
72
  requirements:
79
73
  - - "~>"
80
74
  - !ruby/object:Gem::Version
81
- version: '1.16'
75
+ version: '2.0'
82
76
  type: :development
83
77
  prerelease: false
84
78
  version_requirements: !ruby/object:Gem::Requirement
85
79
  requirements:
86
80
  - - "~>"
87
81
  - !ruby/object:Gem::Version
88
- version: '1.16'
82
+ version: '2.0'
89
83
  - !ruby/object:Gem::Dependency
90
84
  name: rake
91
85
  requirement: !ruby/object:Gem::Requirement
92
86
  requirements:
93
- - - "~>"
87
+ - - ">="
94
88
  - !ruby/object:Gem::Version
95
- version: '10.0'
89
+ version: '0'
96
90
  type: :development
97
91
  prerelease: false
98
92
  version_requirements: !ruby/object:Gem::Requirement
99
93
  requirements:
100
- - - "~>"
94
+ - - ">="
101
95
  - !ruby/object:Gem::Version
102
- version: '10.0'
96
+ version: '0'
103
97
  - !ruby/object:Gem::Dependency
104
98
  name: rspec
105
99
  requirement: !ruby/object:Gem::Requirement
@@ -146,30 +140,16 @@ dependencies:
146
140
  name: database_cleaner
147
141
  requirement: !ruby/object:Gem::Requirement
148
142
  requirements:
149
- - - ">="
150
- - !ruby/object:Gem::Version
151
- version: '0'
152
- type: :development
153
- prerelease: false
154
- version_requirements: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - ">="
157
- - !ruby/object:Gem::Version
158
- version: '0'
159
- - !ruby/object:Gem::Dependency
160
- name: coveralls
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - ">="
143
+ - - "<"
164
144
  - !ruby/object:Gem::Version
165
- version: '0'
145
+ version: '2'
166
146
  type: :development
167
147
  prerelease: false
168
148
  version_requirements: !ruby/object:Gem::Requirement
169
149
  requirements:
170
- - - ">="
150
+ - - "<"
171
151
  - !ruby/object:Gem::Version
172
- version: '0'
152
+ version: '2'
173
153
  - !ruby/object:Gem::Dependency
174
154
  name: simplecov
175
155
  requirement: !ruby/object:Gem::Requirement
@@ -217,7 +197,7 @@ files:
217
197
  homepage: https://github.com/samvera-labs/valkyrie-sequel
218
198
  licenses: []
219
199
  metadata: {}
220
- post_install_message:
200
+ post_install_message:
221
201
  rdoc_options: []
222
202
  require_paths:
223
203
  - lib
@@ -232,9 +212,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
212
  - !ruby/object:Gem::Version
233
213
  version: '0'
234
214
  requirements: []
235
- rubyforge_project:
236
- rubygems_version: 2.6.14
237
- signing_key:
215
+ rubygems_version: 3.1.4
216
+ signing_key:
238
217
  specification_version: 4
239
218
  summary: Valkyrie::MetadataAdapter for Postgres using Sequel.
240
219
  test_files: []