valkyrie 2.0.0 → 2.1.2

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +60 -56
  3. data/.lando.yml +40 -0
  4. data/.rubocop.yml +4 -1
  5. data/.tool-versions +1 -1
  6. data/Appraisals +4 -4
  7. data/CHANGELOG.md +136 -0
  8. data/README.md +21 -49
  9. data/Rakefile +21 -20
  10. data/db/config.yml +3 -10
  11. data/db/schema.rb +0 -40
  12. data/gemfiles/activerecord_5_2.gemfile +2 -0
  13. data/gemfiles/{activerecord_5_1.gemfile → activerecord_6_0.gemfile} +3 -1
  14. data/lib/generators/valkyrie/resource_generator.rb +3 -3
  15. data/lib/valkyrie.rb +33 -15
  16. data/lib/valkyrie/change_set.rb +3 -3
  17. data/lib/valkyrie/id.rb +26 -3
  18. data/lib/valkyrie/indexers/access_controls_indexer.rb +17 -17
  19. data/lib/valkyrie/logging.rb +72 -0
  20. data/lib/valkyrie/persistence/composite_persister.rb +1 -1
  21. data/lib/valkyrie/persistence/fedora.rb +2 -0
  22. data/lib/valkyrie/persistence/fedora/list_node.rb +46 -49
  23. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +2 -2
  24. data/lib/valkyrie/persistence/fedora/ordered_list.rb +90 -90
  25. data/lib/valkyrie/persistence/fedora/ordered_reader.rb +5 -5
  26. data/lib/valkyrie/persistence/fedora/permissive_schema.rb +3 -3
  27. data/lib/valkyrie/persistence/fedora/persister.rb +82 -83
  28. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +16 -17
  29. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +38 -18
  30. data/lib/valkyrie/persistence/fedora/query_service.rb +54 -53
  31. data/lib/valkyrie/persistence/memory/persister.rb +33 -33
  32. data/lib/valkyrie/persistence/memory/query_service.rb +52 -34
  33. data/lib/valkyrie/persistence/postgres/orm_converter.rb +52 -52
  34. data/lib/valkyrie/persistence/postgres/query_service.rb +86 -33
  35. data/lib/valkyrie/persistence/postgres/resource_converter.rb +1 -1
  36. data/lib/valkyrie/persistence/shared/json_value_mapper.rb +4 -2
  37. data/lib/valkyrie/persistence/solr/model_converter.rb +337 -337
  38. data/lib/valkyrie/persistence/solr/orm_converter.rb +3 -3
  39. data/lib/valkyrie/persistence/solr/persister.rb +4 -17
  40. data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +6 -0
  41. data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +1 -1
  42. data/lib/valkyrie/persistence/solr/query_service.rb +42 -53
  43. data/lib/valkyrie/persistence/solr/repository.rb +2 -1
  44. data/lib/valkyrie/rdf_patches.rb +2 -2
  45. data/lib/valkyrie/resource.rb +36 -5
  46. data/lib/valkyrie/specs/shared_specs/change_set.rb +1 -1
  47. data/lib/valkyrie/specs/shared_specs/persister.rb +17 -6
  48. data/lib/valkyrie/specs/shared_specs/queries.rb +112 -9
  49. data/lib/valkyrie/storage/fedora.rb +17 -17
  50. data/lib/valkyrie/storage_adapter.rb +16 -13
  51. data/lib/valkyrie/types.rb +3 -1
  52. data/lib/valkyrie/version.rb +1 -1
  53. data/solr/config/solrconfig.xml +0 -10
  54. data/tasks/dev.rake +14 -51
  55. data/valkyrie.gemspec +4 -4
  56. metadata +40 -37
  57. data/.docker-stack/valkyrie-development/docker-compose.yml +0 -53
  58. data/.docker-stack/valkyrie-test/docker-compose.yml +0 -53
  59. data/db/seeds.rb +0 -8
  60. data/tasks/docker.rake +0 -31
data/Rakefile CHANGED
@@ -6,7 +6,6 @@ require 'config/database_connection'
6
6
  require 'active_record'
7
7
  require 'rubocop/rake_task'
8
8
  load 'tasks/dev.rake'
9
- load 'tasks/docker.rake'
10
9
 
11
10
  RSpec::Core::RakeTask.new(:spec)
12
11
 
@@ -37,8 +36,12 @@ namespace :db do
37
36
 
38
37
  desc 'Create the database from db/config.yml for the current DATABASE_ENV'
39
38
  task create: :configure_connection do
40
- database = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new(@config)
41
- database.create
39
+ begin
40
+ database = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new(@config)
41
+ database.create
42
+ rescue
43
+ puts "Database already exists."
44
+ end
42
45
  puts "Database created"
43
46
  end
44
47
 
@@ -51,25 +54,23 @@ namespace :db do
51
54
 
52
55
  desc 'Migrate the database (options: VERSION=x, VERBOSE=false).'
53
56
  task migrate: :configure_connection do
54
- begin
55
- verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
56
- version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
57
- scope = ENV['SCOPE']
58
- verbose_was = ActiveRecord::Migration.verbose
59
- ActiveRecord::Migration.verbose = verbose
60
- if ActiveRecord::Migrator.respond_to?(:migrate)
61
- ActiveRecord::Migrator.migrate(MIGRATIONS_DIR, version) do |migration|
62
- scope.blank? || scope == migration.scope
63
- end
64
- else
65
- ActiveRecord::Base.connection.migration_context.migrate(version) do |migration|
66
- scope.blank? || scope == migration.scope
67
- end
57
+ verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
58
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
59
+ scope = ENV['SCOPE']
60
+ verbose_was = ActiveRecord::Migration.verbose
61
+ ActiveRecord::Migration.verbose = verbose
62
+ if ActiveRecord::Migrator.respond_to?(:migrate)
63
+ ActiveRecord::Migrator.migrate(MIGRATIONS_DIR, version) do |migration|
64
+ scope.blank? || scope == migration.scope
65
+ end
66
+ else
67
+ ActiveRecord::Base.connection.migration_context.migrate(version) do |migration|
68
+ scope.blank? || scope == migration.scope
68
69
  end
69
- ActiveRecord::Base.clear_cache!
70
- ensure
71
- ActiveRecord::Migration.verbose = verbose_was
72
70
  end
71
+ ActiveRecord::Base.clear_cache!
72
+ ensure
73
+ ActiveRecord::Migration.verbose = verbose_was
73
74
  end
74
75
 
75
76
  namespace :schema do
data/db/config.yml CHANGED
@@ -1,4 +1,3 @@
1
- <% local = File.exist?('/tmp/.s.PGSQL.5432') && File.stat('/tmp/.s.PGSQL.5432').socket? %>
2
1
  default: &default
3
2
  adapter: postgresql
4
3
  encoding: utf8
@@ -6,22 +5,16 @@ default: &default
6
5
  pool: <%= Integer(ENV.fetch("DB_POOL", 5)) %>
7
6
  reaping_frequency: <%= Integer(ENV.fetch("DB_REAPING_FREQUENCY", 10)) %>
8
7
  timeout: 5000
9
- <% unless local %>
10
8
  host: localhost
11
- username: docker
12
- password: d0ck3r
13
- <% end %>
9
+ username: postgres
10
+ password:
14
11
 
15
12
  development:
16
13
  <<: *default
17
14
  database: Valkyrie_gem_development
18
- <% unless local %>
19
15
  port: 5433
20
- <% end %>
21
16
 
22
17
  test:
23
18
  <<: *default
24
19
  database: Valkyrie_gem_test
25
- <% unless local %>
26
- port: 5434
27
- <% end %>
20
+ port: <%= ENV["POSTGRES_PORT"] || 5433 %>
data/db/schema.rb CHANGED
@@ -15,18 +15,6 @@ ActiveRecord::Schema.define(version: 20170531004548) do
15
15
  enable_extension "plpgsql"
16
16
  enable_extension "uuid-ossp"
17
17
 
18
- create_table "bookmarks", id: :serial, force: :cascade do |t|
19
- t.integer "user_id", null: false
20
- t.string "user_type"
21
- t.string "document_id"
22
- t.string "document_type"
23
- t.binary "title"
24
- t.datetime "created_at", null: false
25
- t.datetime "updated_at", null: false
26
- t.index ["document_id"], name: "index_bookmarks_on_document_id"
27
- t.index ["user_id"], name: "index_bookmarks_on_user_id"
28
- end
29
-
30
18
  create_table "orm_resources", id: :uuid, default: -> { "uuid_generate_v4()" }, force: :cascade do |t|
31
19
  t.jsonb "metadata", default: {}, null: false
32
20
  t.datetime "created_at", null: false
@@ -34,32 +22,4 @@ ActiveRecord::Schema.define(version: 20170531004548) do
34
22
  t.string "internal_resource"
35
23
  t.index ["metadata"], name: "index_orm_resources_on_metadata", using: :gin
36
24
  end
37
-
38
- create_table "searches", id: :serial, force: :cascade do |t|
39
- t.binary "query_params"
40
- t.integer "user_id"
41
- t.string "user_type"
42
- t.datetime "created_at", null: false
43
- t.datetime "updated_at", null: false
44
- t.index ["user_id"], name: "index_searches_on_user_id"
45
- end
46
-
47
- create_table "users", id: :serial, force: :cascade do |t|
48
- t.string "email", default: "", null: false
49
- t.string "encrypted_password", default: "", null: false
50
- t.string "reset_password_token"
51
- t.datetime "reset_password_sent_at"
52
- t.datetime "remember_created_at"
53
- t.integer "sign_in_count", default: 0, null: false
54
- t.datetime "current_sign_in_at"
55
- t.datetime "last_sign_in_at"
56
- t.inet "current_sign_in_ip"
57
- t.inet "last_sign_in_ip"
58
- t.datetime "created_at", null: false
59
- t.datetime "updated_at", null: false
60
- t.boolean "guest", default: false
61
- t.index ["email"], name: "index_users_on_email", unique: true
62
- t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
63
- end
64
-
65
25
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file was generated by Appraisal
2
4
 
3
5
  source "https://rubygems.org"
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file was generated by Appraisal
2
4
 
3
5
  source "https://rubygems.org"
4
6
 
5
- gem "activerecord", "~> 5.1.0"
7
+ gem "activerecord", "~> 6.0.0"
6
8
  gem "ldp"
7
9
  gem "pg"
8
10
  gem "rsolr"
@@ -21,7 +21,7 @@ class Valkyrie::ResourceGenerator < Rails::Generators::NamedBase
21
21
 
22
22
  private
23
23
 
24
- def rspec_installed?
25
- defined?(RSpec) && defined?(RSpec::Rails)
26
- end
24
+ def rspec_installed?
25
+ defined?(RSpec) && defined?(RSpec::Rails)
26
+ end
27
27
  end
data/lib/valkyrie.rb CHANGED
@@ -14,6 +14,7 @@ require 'logger'
14
14
  require 'rdf/vocab'
15
15
 
16
16
  module Valkyrie
17
+ require 'valkyrie/logging'
17
18
  require 'valkyrie/id'
18
19
  require 'valkyrie/change_set'
19
20
  require 'valkyrie/value_mapper'
@@ -61,12 +62,16 @@ module Valkyrie
61
62
  end
62
63
  end
63
64
 
65
+ # @return [Valkyrie::Logging]
64
66
  def logger
65
- @logger ||= Logger.new(STDOUT)
67
+ @logger ||= Valkyrie::Logging.new(logger: Logger.new(STDOUT))
66
68
  end
67
69
 
70
+ # Wraps the given logger in an instance of Valkyrie::Logging
71
+ #
72
+ # @param logger [Logger]
68
73
  def logger=(logger)
69
- @logger = logger
74
+ @logger = Valkyrie::Logging.new(logger: logger)
70
75
  end
71
76
 
72
77
  class Config < OpenStruct
@@ -82,6 +87,19 @@ module Valkyrie
82
87
  Valkyrie::StorageAdapter.find(super.to_sym)
83
88
  end
84
89
 
90
+ # @api public
91
+ # Configure id_string_equality to be true in order to make Valkyrie::ID
92
+ # equal to the string value they contain. This will be the default behavior
93
+ # in v3.0.0.
94
+ #
95
+ # @return [Boolean] Whether `Valkyrie::ID` should be equal to their string counterpart.
96
+ def id_string_equality
97
+ super
98
+ end
99
+
100
+ # @!attribute [w] id_string_equality=
101
+ # The setter for #id_string_equality; see it's implementation
102
+
85
103
  # @api public
86
104
  #
87
105
  # The returned anonymous method (e.g. responds to #call) has a signature of
@@ -101,19 +119,19 @@ module Valkyrie
101
119
 
102
120
  private
103
121
 
104
- def defaults
105
- {
106
- resource_class_resolver: method(:default_resource_class_resolver)
107
- }
108
- end
109
-
110
- # String constantize is a "by convention" factory. This works, but assumes
111
- # the ruby class once used to persist is the model used to now reify.
112
- #
113
- # @param [String] class_name
114
- def default_resource_class_resolver(class_name)
115
- class_name.constantize
116
- end
122
+ def defaults
123
+ {
124
+ resource_class_resolver: method(:default_resource_class_resolver)
125
+ }
126
+ end
127
+
128
+ # String constantize is a "by convention" factory. This works, but assumes
129
+ # the ruby class once used to persist is the model used to now reify.
130
+ #
131
+ # @param [String] class_name
132
+ def default_resource_class_resolver(class_name)
133
+ class_name.constantize
134
+ end
117
135
  end
118
136
 
119
137
  module_function :config, :logger, :logger=, :config_root_path, :environment, :config_file, :config_hash
@@ -104,8 +104,8 @@ module Valkyrie
104
104
 
105
105
  private
106
106
 
107
- def field(field_name)
108
- self.class.definitions.fetch(field_name.to_s)
109
- end
107
+ def field(field_name)
108
+ self.class.definitions.fetch(field_name.to_s)
109
+ end
110
110
  end
111
111
  end
data/lib/valkyrie/id.rb CHANGED
@@ -10,21 +10,44 @@ module Valkyrie
10
10
  @id = id.to_s
11
11
  end
12
12
 
13
+ ##
14
+ # @return [String]
13
15
  def to_s
16
+ to_str
17
+ end
18
+
19
+ ##
20
+ # @return [String]
21
+ def to_str
14
22
  id
15
23
  end
16
24
 
17
25
  delegate :hash, to: :state
18
26
 
19
27
  def eql?(other)
20
- other.class == self.class && other.state == state
28
+ return string_equality(other) if Valkyrie.config.id_string_equality == true
29
+ default_equality(other)
21
30
  end
22
31
  alias == eql?
23
32
 
24
33
  protected
25
34
 
26
- def state
27
- [@id]
35
+ def default_equality(other)
36
+ output = (other.class == self.class && other.state == state)
37
+ return output if output == true
38
+ if output == false && string_equality(other) && Valkyrie.config.id_string_equality.nil?
39
+ warn "[DEPRECATION] Valkyrie::IDs will always be equal to their string counterparts in 3.0.0. " \
40
+ "To silence this message, please either compare IDs or set Valkyrie.config.id_string_equality = true."
28
41
  end
42
+ false
43
+ end
44
+
45
+ def string_equality(other)
46
+ other == to_str
47
+ end
48
+
49
+ def state
50
+ [@id]
51
+ end
29
52
  end
30
53
  end
@@ -40,24 +40,24 @@ module Valkyrie::Indexers
40
40
 
41
41
  private
42
42
 
43
- # rubocop:disable Metrics/MethodLength
44
- def default_config
45
- if defined?(Hydra) && Hydra.respond_to?(:config)
46
- {
47
- read_groups: Hydra.config[:permissions][:read].group,
48
- read_users: Hydra.config[:permissions][:read].individual,
49
- edit_groups: Hydra.config[:permissions][:edit].group,
50
- edit_users: Hydra.config[:permissions][:edit].individual
51
- }
52
- else
53
- {
54
- read_groups: 'read_access_group_ssim',
55
- read_users: 'read_access_person_ssim',
56
- edit_groups: 'edit_access_group_ssim',
57
- edit_users: 'edit_access_person_ssim'
58
- }
59
- end
43
+ # rubocop:disable Metrics/MethodLength
44
+ def default_config
45
+ if defined?(Hydra) && Hydra.respond_to?(:config)
46
+ {
47
+ read_groups: Hydra.config[:permissions][:read].group,
48
+ read_users: Hydra.config[:permissions][:read].individual,
49
+ edit_groups: Hydra.config[:permissions][:edit].group,
50
+ edit_users: Hydra.config[:permissions][:edit].individual
51
+ }
52
+ else
53
+ {
54
+ read_groups: 'read_access_group_ssim',
55
+ read_users: 'read_access_person_ssim',
56
+ edit_groups: 'edit_access_group_ssim',
57
+ edit_users: 'edit_access_person_ssim'
58
+ }
60
59
  end
60
+ end
61
61
  # rubocop:enable Metrics/MethodLength
62
62
  end
63
63
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie
3
+ # A wrapper class for Valkyrie logging. This class attempts to provide
4
+ # tooling that helps improve the communication through-out the stack.
5
+ #
6
+ # In gem development there are several considerations regarding logging.
7
+ #
8
+ # 1) The development on the gem directly, in particular specs
9
+ # 2) The downstream development that leverages the gem, both when specs are
10
+ # running and when running the downstream processes in a development
11
+ # environment.
12
+ # 3) The downstream behaviors that are called in production environments.
13
+ #
14
+ # In each of these cases, different considerations regarding logging may be
15
+ # relevant.
16
+ #
17
+ # In the below example,
18
+ #
19
+ # @example
20
+ # Valkyrie.logger.suppress_logging_for_contexts!("A Named Context") do
21
+ # # The following will NOT be logged
22
+ # Valkyrie.logger.warn('Hello', logging_context: "A Named Context")
23
+ #
24
+ # # The following will be logged
25
+ # Valkyrie.logger.warn('Hello')
26
+ # end
27
+ # # The following will be logged
28
+ # Valkyrie.logger.warn('Hello', logging_context: "A Named Context")
29
+
30
+ class Logging < SimpleDelegator
31
+ # @param logger [Logger] the logger to which we'll delegate messages
32
+ def initialize(logger:)
33
+ @suppressions = {}
34
+ super(logger)
35
+ end
36
+
37
+ def warn(*args, logging_context: false, &block)
38
+ super(*args, *block) unless @suppressions.key?(logging_context)
39
+ end
40
+
41
+ def error(*args, logging_context: false, &block)
42
+ super(*args, *block) unless @suppressions.key?(logging_context)
43
+ end
44
+
45
+ def info(*args, logging_context: false, &block)
46
+ super(*args, *block) unless @suppressions.key?(logging_context)
47
+ end
48
+
49
+ def debug(*args, logging_context: false, &block)
50
+ super(*args, *block) unless @suppressions.key?(logging_context)
51
+ end
52
+
53
+ def fatal(*args, logging_context: false, &block)
54
+ super(*args, *block) unless @suppressions.key?(logging_context)
55
+ end
56
+
57
+ def suppress_logging_for_contexts!(*logging_contexts)
58
+ Array(logging_contexts).each do |logging_context|
59
+ @suppressions[logging_context] = true
60
+ end
61
+ return unless block_given?
62
+ yield
63
+ clear_suppressions!(*logging_contexts)
64
+ end
65
+
66
+ def clear_suppressions!(*logging_contexts)
67
+ Array(logging_contexts).each do |logging_context|
68
+ @suppressions.delete(logging_context)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -30,7 +30,7 @@ module Valkyrie::Persistence
30
30
  cached_resource = first.save(resource: resource)
31
31
  # Don't pass opt lock tokens to other persisters
32
32
  internal_resource = cached_resource.dup
33
- internal_resource.send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", []) if internal_resource.optimistic_locking_enabled?
33
+ internal_resource.clear_optimistic_lock_token!
34
34
  rest.inject(internal_resource) { |m, persister| persister.save(resource: m) }
35
35
  # return the one with the desired opt lock token
36
36
  cached_resource
@@ -19,5 +19,7 @@ module Valkyrie::Persistence
19
19
  require 'valkyrie/persistence/fedora/ordered_list'
20
20
  require 'valkyrie/persistence/fedora/ordered_reader'
21
21
  require 'valkyrie/persistence/fedora/list_node'
22
+
23
+ DEFAULT_FEDORA_VERSION = 5
22
24
  end
23
25
  end