valkyrie 0.0.0 → 0.1.0

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -3
  3. data/.rubocop.yml +28 -0
  4. data/Gemfile +6 -1
  5. data/README.md +145 -10
  6. data/Rakefile +59 -1
  7. data/bin/console +1 -1
  8. data/config/valkyrie.yml +8 -0
  9. data/db/config.yml +17 -0
  10. data/db/migrate/20160111215816_enable_uuid_extension.rb +6 -0
  11. data/db/migrate/20161007101725_create_orm_resources.rb +10 -0
  12. data/db/migrate/20170124135846_add_model_type_to_orm_resources.rb +6 -0
  13. data/db/migrate/20170531004548_change_model_type_to_internal_model.rb +6 -0
  14. data/db/schema.rb +65 -0
  15. data/db/seeds.rb +8 -0
  16. data/lib/config/database_connection.rb +15 -0
  17. data/lib/generators/valkyrie/resource_generator.rb +27 -0
  18. data/lib/generators/valkyrie/templates/resource.rb.erb +9 -0
  19. data/lib/generators/valkyrie/templates/resource_spec.rb.erb +13 -0
  20. data/lib/valkyrie.rb +76 -1
  21. data/lib/valkyrie/adapter_container.rb +12 -0
  22. data/lib/valkyrie/change_set.rb +84 -0
  23. data/lib/valkyrie/decorators/decorator_list.rb +15 -0
  24. data/lib/valkyrie/decorators/decorator_with_arguments.rb +14 -0
  25. data/lib/valkyrie/derivative_service.rb +42 -0
  26. data/lib/valkyrie/engine.rb +10 -0
  27. data/lib/valkyrie/file_characterization_service.rb +42 -0
  28. data/lib/valkyrie/id.rb +32 -0
  29. data/lib/valkyrie/indexers/access_controls_indexer.rb +19 -0
  30. data/lib/valkyrie/local_file_service.rb +11 -0
  31. data/lib/valkyrie/metadata_adapter.rb +22 -0
  32. data/lib/valkyrie/persist_derivatives.rb +29 -0
  33. data/lib/valkyrie/persistence.rb +14 -0
  34. data/lib/valkyrie/persistence/buffered_persister.rb +28 -0
  35. data/lib/valkyrie/persistence/composite_persister.rb +29 -0
  36. data/lib/valkyrie/persistence/delete_tracking_buffer.rb +21 -0
  37. data/lib/valkyrie/persistence/fedora.rb +11 -0
  38. data/lib/valkyrie/persistence/fedora/list_node.rb +88 -0
  39. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +45 -0
  40. data/lib/valkyrie/persistence/fedora/ordered_list.rb +146 -0
  41. data/lib/valkyrie/persistence/fedora/ordered_reader.rb +28 -0
  42. data/lib/valkyrie/persistence/fedora/persister.rb +47 -0
  43. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +199 -0
  44. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +338 -0
  45. data/lib/valkyrie/persistence/fedora/persister/resource_factory.rb +21 -0
  46. data/lib/valkyrie/persistence/fedora/query_service.rb +80 -0
  47. data/lib/valkyrie/persistence/memory.rb +8 -0
  48. data/lib/valkyrie/persistence/memory/metadata_adapter.rb +22 -0
  49. data/lib/valkyrie/persistence/memory/persister.rb +58 -0
  50. data/lib/valkyrie/persistence/memory/query_service.rb +86 -0
  51. data/lib/valkyrie/persistence/postgres.rb +6 -0
  52. data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +20 -0
  53. data/lib/valkyrie/persistence/postgres/orm.rb +9 -0
  54. data/lib/valkyrie/persistence/postgres/orm/resource.rb +7 -0
  55. data/lib/valkyrie/persistence/postgres/orm_converter.rb +118 -0
  56. data/lib/valkyrie/persistence/postgres/persister.rb +33 -0
  57. data/lib/valkyrie/persistence/postgres/queries.rb +8 -0
  58. data/lib/valkyrie/persistence/postgres/queries/find_inverse_references_query.rb +31 -0
  59. data/lib/valkyrie/persistence/postgres/queries/find_members_query.rb +33 -0
  60. data/lib/valkyrie/persistence/postgres/queries/find_references_query.rb +33 -0
  61. data/lib/valkyrie/persistence/postgres/query_service.rb +53 -0
  62. data/lib/valkyrie/persistence/postgres/resource_converter.rb +18 -0
  63. data/lib/valkyrie/persistence/postgres/resource_factory.rb +30 -0
  64. data/lib/valkyrie/persistence/solr.rb +6 -0
  65. data/lib/valkyrie/persistence/solr/metadata_adapter.rb +42 -0
  66. data/lib/valkyrie/persistence/solr/model_converter.rb +270 -0
  67. data/lib/valkyrie/persistence/solr/orm_converter.rb +252 -0
  68. data/lib/valkyrie/persistence/solr/persister.rb +32 -0
  69. data/lib/valkyrie/persistence/solr/queries.rb +11 -0
  70. data/lib/valkyrie/persistence/solr/queries/default_paginator.rb +16 -0
  71. data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +33 -0
  72. data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +24 -0
  73. data/lib/valkyrie/persistence/solr/queries/find_inverse_references_query.rb +30 -0
  74. data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +43 -0
  75. data/lib/valkyrie/persistence/solr/queries/find_references_query.rb +34 -0
  76. data/lib/valkyrie/persistence/solr/query_service.rb +48 -0
  77. data/lib/valkyrie/persistence/solr/repository.rb +36 -0
  78. data/lib/valkyrie/persistence/solr/resource_factory.rb +24 -0
  79. data/lib/valkyrie/rdf_patches.rb +17 -0
  80. data/lib/valkyrie/resource.rb +106 -0
  81. data/lib/valkyrie/resource/access_controls.rb +13 -0
  82. data/lib/valkyrie/specs/shared_specs.rb +10 -0
  83. data/lib/valkyrie/specs/shared_specs/change_set_persister.rb +60 -0
  84. data/lib/valkyrie/specs/shared_specs/derivative_service.rb +30 -0
  85. data/lib/valkyrie/specs/shared_specs/file.rb +12 -0
  86. data/lib/valkyrie/specs/shared_specs/file_characterization_service.rb +33 -0
  87. data/lib/valkyrie/specs/shared_specs/metadata_adapter.rb +10 -0
  88. data/lib/valkyrie/specs/shared_specs/persister.rb +154 -0
  89. data/lib/valkyrie/specs/shared_specs/queries.rb +128 -0
  90. data/lib/valkyrie/specs/shared_specs/resource.rb +71 -0
  91. data/lib/valkyrie/specs/shared_specs/storage_adapter.rb +44 -0
  92. data/lib/valkyrie/storage.rb +8 -0
  93. data/lib/valkyrie/storage/disk.rb +55 -0
  94. data/lib/valkyrie/storage/fedora.rb +71 -0
  95. data/lib/valkyrie/storage/memory.rb +31 -0
  96. data/lib/valkyrie/storage_adapter.rb +100 -0
  97. data/lib/valkyrie/types.rb +34 -0
  98. data/lib/valkyrie/value_mapper.rb +67 -0
  99. data/lib/valkyrie/version.rb +2 -1
  100. data/lib/valkyrie/vocab/pcdm_use.rb +73 -0
  101. data/valkyrie.gemspec +33 -7
  102. metadata +462 -7
  103. data/.travis.yml +0 -5
data/db/seeds.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ # This file should contain all the record creation needed to seed the database with its default values.
3
+ # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
4
+ #
5
+ # Examples:
6
+ #
7
+ # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
8
+ # Character.create(name: 'Luke', movie: movies.first)
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ require 'active_record'
3
+ require 'erb'
4
+
5
+ module DatabaseConnection
6
+ def self.connect!(env)
7
+ # Ref https://github.com/puma/puma#clustered-mode
8
+ ActiveSupport.on_load(:active_record) do
9
+ ::ActiveRecord::Base.connection_pool.disconnect! if ::ActiveRecord::Base.connected?
10
+ ::ActiveRecord::Base.configurations = YAML.safe_load(ERB.new(File.read("db/config.yml")).result) || {}
11
+ config = ::ActiveRecord::Base.configurations[env.to_s]
12
+ ::ActiveRecord::Base.establish_connection(config)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ require 'rails/generators'
3
+ require 'rails/generators/model_helpers'
4
+
5
+ class Valkyrie::ResourceGenerator < Rails::Generators::NamedBase
6
+ # Include ModelHelpers to warn about pluralization when generating new models or scaffolds
7
+ include Rails::Generators::ModelHelpers
8
+
9
+ source_root File.expand_path('../templates', __FILE__)
10
+
11
+ argument :attributes, type: :array, default: [], banner: 'field:type field:type'
12
+
13
+ def create_model
14
+ template('resource.rb.erb', File.join('app/models', class_path, "#{file_name}.rb"))
15
+ end
16
+
17
+ def create_model_spec
18
+ return unless rspec_installed?
19
+ template('resource_spec.rb.erb', File.join('spec/models', class_path, "#{file_name}_spec.rb"))
20
+ end
21
+
22
+ private
23
+
24
+ def rspec_installed?
25
+ defined?(RSpec) && defined?(RSpec::Rails)
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ # Generated with `rails generate valkyrie:model <%= class_name %>`
3
+ class <%= class_name %> < Valkyrie::Resource
4
+ include Valkyrie::Resource::AccessControls
5
+ attribute :id, Valkyrie::Types::ID.optional
6
+ <%- attributes.each do |att| -%>
7
+ attribute :<%= att.name %>, Valkyrie::Types::<%= (att.type == :array) ? 'Array' : 'Set' %>
8
+ <%- end -%>
9
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # Generated with `rails generate valkyrie:model <%= class_name %>`
3
+ require 'rails_helper'
4
+ require 'valkyrie/specs/shared_specs'
5
+
6
+ RSpec.describe <%= class_name %> do
7
+ let(:model_klass) { described_class }
8
+ it_behaves_like "a Valkyrie::Resource"
9
+
10
+ it "has tests" do
11
+ skip "Add your tests here"
12
+ end
13
+ end
data/lib/valkyrie.rb CHANGED
@@ -1,5 +1,80 @@
1
+ # frozen_string_literal: true
1
2
  require "valkyrie/version"
3
+ require "ostruct"
4
+ require 'active_support'
5
+ require 'active_support/core_ext'
6
+ require 'dry-types'
7
+ require 'dry-struct'
8
+ require 'draper'
9
+ require 'active_record'
10
+ require 'reform'
11
+ require 'reform/active_record'
12
+ require 'rdf'
13
+ require 'valkyrie/rdf_patches'
14
+ require 'json/ld'
15
+ require 'logger'
16
+ require 'active_triples'
17
+ require 'rdf/vocab'
18
+ require 'active_fedora'
19
+ require 'hydra-access-controls'
20
+ require 'ruby_tika_app'
2
21
 
22
+ # frozen_string_literal: true
3
23
  module Valkyrie
4
- # Your code goes here...
24
+ require 'valkyrie/id'
25
+ require 'valkyrie/change_set'
26
+ require 'valkyrie/value_mapper'
27
+ require 'valkyrie/persistence'
28
+ require 'valkyrie/types'
29
+ require 'valkyrie/resource'
30
+ require 'valkyrie/derivative_service'
31
+ require 'valkyrie/storage_adapter'
32
+ require 'valkyrie/metadata_adapter'
33
+ require 'valkyrie/adapter_container'
34
+ require 'valkyrie/file_characterization_service'
35
+ require 'valkyrie/decorators/decorator_list'
36
+ require 'valkyrie/decorators/decorator_with_arguments'
37
+ require 'valkyrie/resource/access_controls'
38
+ require 'valkyrie/indexers/access_controls_indexer'
39
+ require 'valkyrie/storage'
40
+ require 'valkyrie/vocab/pcdm_use'
41
+ require 'generators/valkyrie/resource_generator'
42
+ require 'valkyrie/engine' if defined?(Rails)
43
+ def config
44
+ @config ||= Config.new(
45
+ YAML.safe_load(ERB.new(File.read(config_root_path.join("config", "valkyrie.yml"))).result)[environment]
46
+ )
47
+ end
48
+
49
+ def environment
50
+ Rails.env
51
+ end
52
+
53
+ def config_root_path
54
+ if const_defined?(:Rails) && Rails.root
55
+ Rails.root
56
+ else
57
+ Pathname.new(Dir.pwd)
58
+ end
59
+ end
60
+
61
+ def logger
62
+ @logger ||= Logger.new(STDOUT)
63
+ end
64
+
65
+ def logger=(logger)
66
+ @logger = logger
67
+ end
68
+
69
+ class Config < OpenStruct
70
+ def metadata_adapter
71
+ Valkyrie::MetadataAdapter.find(super.to_sym)
72
+ end
73
+
74
+ def storage_adapter
75
+ Valkyrie::StorageAdapter.find(super.to_sym)
76
+ end
77
+ end
78
+
79
+ module_function :config, :logger, :logger=, :config_root_path, :environment
5
80
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie
3
+ class AdapterContainer
4
+ # Wraps up an individual persister and query service to conform to the
5
+ # adapter interface. Useful for decorated persisters.
6
+ attr_reader :persister, :query_service
7
+ def initialize(persister:, query_service:)
8
+ @persister = persister
9
+ @query_service = query_service
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+ require 'reform/form/coercion'
3
+ require 'reform/form/active_model/validations'
4
+ module Valkyrie
5
+ ##
6
+ # Standard change set object for Valkyrie.
7
+ # ChangeSets are a way to group together properties that should be applied to
8
+ # an underlying resource. They are often used for powering HTML Forms or
9
+ # storing virtual attributes for special synchronization with a resource.
10
+ # @example Define a change set
11
+ # class BookChangeSet < Valkyrie::ChangeSet
12
+ # self.fields = [:title, :author]
13
+ # validates :title, presence: true
14
+ # property :title, multiple: false, required: true
15
+ # end
16
+ class ChangeSet < Reform::Form
17
+ include Reform::Form::ActiveModel::Validations
18
+ feature Coercion
19
+ class_attribute :fields
20
+ self.fields = []
21
+
22
+ property :append_id, virtual: true
23
+
24
+ # Set ID of record this one should be appended to.
25
+ # @param append_id [Valkyrie::ID]
26
+ def append_id=(append_id)
27
+ super(Valkyrie::ID.new(append_id))
28
+ end
29
+
30
+ # Returns whether or not a given field has multiple values.
31
+ # @param field [Symbol]
32
+ # @return [Boolean]
33
+ def multiple?(field)
34
+ self.class.definitions[field.to_s][:multiple] != false
35
+ end
36
+
37
+ # Returns whether or not a given field is required.
38
+ # @param field [Symbol]
39
+ # @return [Boolean]
40
+ def required?(field)
41
+ self.class.definitions[field.to_s][:required]
42
+ end
43
+
44
+ # Quick setter for fields that should be in a changeset. Defaults to multiple,
45
+ # not required, with an empty array default.
46
+ # @param fields [Array<Symbol>]
47
+ def self.fields=(fields)
48
+ singleton_class.class_eval do
49
+ remove_possible_method(:fields)
50
+ define_method(:fields) { fields }
51
+ end
52
+
53
+ fields.each do |field|
54
+ property field, default: []
55
+ end
56
+ fields
57
+ end
58
+
59
+ # Returns value for a given property.
60
+ # @param key [Symbol]
61
+ def [](key)
62
+ send(key) if respond_to?(key)
63
+ end
64
+
65
+ delegate :attributes, to: :resource
66
+
67
+ delegate :internal_resource, :created_at, :updated_at, :model_name, to: :resource
68
+
69
+ # Prepopulates all fields with defaults defined in the changeset. This is an
70
+ # override of Reform::Form's method to allow for single-valued fields to
71
+ # prepopulate appropriately.
72
+ def prepopulate!(_options = {})
73
+ self.class.definitions.select { |_field, definition| definition[:multiple] == false }.each do |field, _definition|
74
+ value = Array.wrap(send(field.to_s)).first
75
+ send("#{field}=", value)
76
+ end
77
+ self
78
+ end
79
+
80
+ def resource
81
+ model
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie::Decorators
3
+ class DecoratorList
4
+ attr_reader :decorators
5
+ def initialize(*decorators)
6
+ @decorators = decorators
7
+ end
8
+
9
+ def new(undecorated_object)
10
+ decorators.inject(undecorated_object) do |obj, decorator|
11
+ decorator.new(obj)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie::Decorators
3
+ class DecoratorWithArguments
4
+ attr_reader :decorator, :args
5
+ def initialize(decorator, *args)
6
+ @decorator = decorator
7
+ @args = args
8
+ end
9
+
10
+ def new(item)
11
+ decorator.new(item, *args)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ require 'hydra/derivatives'
3
+ module Valkyrie
4
+ ##
5
+ # Container for registering DerivativeServices.
6
+ #
7
+ # To add a new service:
8
+ # DerivativeService.services << MyDerivativeService
9
+ class DerivativeService
10
+ require 'valkyrie/local_file_service'
11
+ require 'valkyrie/persist_derivatives'
12
+ Hydra::Derivatives.source_file_service = Valkyrie::LocalFileService
13
+ Hydra::Derivatives.output_file_service = Valkyrie::PersistDerivatives
14
+ class_attribute :services
15
+ self.services = []
16
+ # Returns a derivative service for a change_set.
17
+ # @param resource [Valkyrie::ChangeSet]
18
+ # @return [Valkyrie::DerivativeService]
19
+ def self.for(change_set)
20
+ services.map { |service| service.new(change_set) }.find(&:valid?) ||
21
+ new(change_set)
22
+ end
23
+ attr_reader :change_set
24
+ delegate :mime_type, :uri, to: :change_set
25
+ # @param resource [Valkyrie::Resource]
26
+ def initialize(change_set)
27
+ @change_set = change_set
28
+ end
29
+
30
+ # Deletes any derivatives generated.
31
+ def cleanup_derivatives; end
32
+
33
+ # Creates derivatives.
34
+ def create_derivatives; end
35
+
36
+ # Returns true if the given resource is valid for this derivative service.
37
+ # @return [Boolean]
38
+ def valid?
39
+ true
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ ##
3
+ # This engine exists for the sole purpose of enabling the
4
+ # `valkyrie_engine:install:migrations` rake task from an including Rails
5
+ # application. It technically enables a whole host of other functionality -
6
+ # don't use it, please.
7
+ module Valkyrie
8
+ class Engine < Rails::Engine
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ require 'ruby_tika_app'
3
+
4
+ module Valkyrie
5
+ # Abstract base class for file characterization
6
+ # registers file characterization service a ValkyrieFileCharacterization service
7
+ # initializes the interface for file characterization
8
+ # @since 0.1.0
9
+ class FileCharacterizationService
10
+ class_attribute :services
11
+ self.services = []
12
+ # initializes the file characterization service
13
+ # @param file_node [FileNode] the FileNode to be characterized
14
+ # @param persister [AppendingPersister] the Persister used to save the FileNode
15
+ # @return [TikaFileCharacterizationService] the file characterization service, currently only TikaFileCharacterizationService is implemented
16
+ def self.for(file_node:, persister:)
17
+ services.map { |service| service.new(file_node: file_node, persister: persister) }.find(&:valid?) ||
18
+ new(file_node: file_node, persister: persister)
19
+ end
20
+ attr_reader :file_node, :persister
21
+ delegate :mime_type, :height, :width, :checksum, to: :file_node
22
+ def initialize(file_node:, persister:)
23
+ @file_node = file_node
24
+ @persister = persister
25
+ end
26
+
27
+ # characterizes the file_node passed into this service
28
+ # Default options are:
29
+ # save: true
30
+ # @param save [Boolean] should the persister save the file_node after Characterization
31
+ # @return [FileNode]
32
+ def characterize(save: true)
33
+ persister.save(resource: @file_node) if save
34
+ @file_node
35
+ end
36
+
37
+ # Stub function that sets this service as valid for all FileNode types
38
+ def valid?
39
+ true
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie
3
+ class ID
4
+ attr_reader :id
5
+ delegate :empty?, to: :id
6
+ def initialize(id)
7
+ @id = id.to_s
8
+ end
9
+
10
+ def to_s
11
+ id
12
+ end
13
+
14
+ delegate :hash, to: :state
15
+
16
+ def eql?(other)
17
+ other.class == self.class && other.state == state
18
+ end
19
+ alias == eql?
20
+
21
+ def to_uri
22
+ return RDF::Literal.new(id.to_s, datatype: RDF::URI("http://example.com/valkyrie_id")) if id.to_s.include?("://")
23
+ ::RDF::URI(ActiveFedora::Base.id_to_uri(id))
24
+ end
25
+
26
+ protected
27
+
28
+ def state
29
+ [@id]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie::Indexers
3
+ class AccessControlsIndexer
4
+ attr_reader :resource
5
+ def initialize(resource:)
6
+ @resource = resource
7
+ end
8
+
9
+ def to_solr
10
+ return {} unless resource.respond_to?(:read_users)
11
+ {
12
+ Hydra.config[:permissions][:read].group => resource.read_groups,
13
+ Hydra.config[:permissions][:read].individual => resource.read_users,
14
+ Hydra.config[:permissions][:edit].individual => resource.edit_users,
15
+ Hydra.config[:permissions][:edit].group => resource.edit_groups
16
+ }
17
+ end
18
+ end
19
+ end