valkyrie 2.0.0 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
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