-
Notifications
You must be signed in to change notification settings - Fork 124
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dymanic loading of the model with m3 profiles
- Loading branch information
1 parent
3d32fa7
commit 01b8ed1
Showing
12 changed files
with
428 additions
and
12 deletions.
There are no files selected for viewing
10 changes: 10 additions & 0 deletions
10
.dassie/db/migrate/20240606205215_create_hyrax_flexible_schemas.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
class CreateHyraxFlexibleSchemas < ActiveRecord::Migration[6.1] | ||
def change | ||
create_table :hyrax_flexible_schemas do |t| | ||
t.string :version, index: { unique: true } | ||
t.text :profile | ||
|
||
t.timestamps | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
class Hyrax::FlexibleSchema < ApplicationRecord | ||
serialize :profile, coder: YAML | ||
|
||
def attributes_for(class_name) | ||
class_names[class_name] | ||
end | ||
|
||
def class_names | ||
return @class_names if @class_names | ||
@class_names = {} | ||
profile['classes'].keys.each do |class_name| | ||
@class_names[class_name] = {} | ||
end | ||
profile['properties'].each do |key, value| | ||
value['available_on']['class'].each do |property_class| | ||
# map some m3 items to what Hyrax expects | ||
value['type'] = lookup_type(value['range']) | ||
value['predicate'] = value['property_uri'] | ||
@class_names[property_class][key] = value | ||
end | ||
end | ||
@class_names | ||
end | ||
|
||
def lookup_type(range) | ||
case range | ||
when "http://www.w3.org/2001/XMLSchema#dateTime" | ||
'date_time' | ||
else | ||
range.split('#').last.underscore | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# frozen_string_literal: true | ||
|
||
module Hyrax | ||
## | ||
# @api private | ||
# | ||
# Read m3 profiles from the database | ||
# | ||
# @see config/metadata/m3_profile.yaml for an example configuration | ||
class M3SchemaLoader | ||
## | ||
# @param [Symbol] schema | ||
# | ||
# @return [Hash<Symbol, Dry::Types::Type>] a map from attribute names to | ||
# types | ||
def attributes_for(schema:, version: 1) | ||
definitions(schema, version).each_with_object({}) do |definition, hash| | ||
hash[definition.name] = definition.type.meta(definition.config) | ||
end | ||
end | ||
|
||
## | ||
# @param [Symbol] schema | ||
# | ||
# @return [Hash{Symbol => Hash{Symbol => Object}}] | ||
def form_definitions_for(schema:, version: 1) | ||
definitions(schema, version).each_with_object({}) do |definition, hash| | ||
next if definition.form_options.empty? | ||
|
||
hash[definition.name] = definition.form_options | ||
end | ||
end | ||
|
||
## | ||
# @param [Symbol] schema | ||
# | ||
# @return [{Symbol => Symbol}] a map from index keys to attribute names | ||
def index_rules_for(schema:, version: 1) | ||
definitions(schema, version).each_with_object({}) do |definition, hash| | ||
definition.index_keys.each do |key| | ||
hash[key] = definition.name | ||
end | ||
end | ||
end | ||
|
||
## | ||
# @api private | ||
class AttributeDefinition | ||
## | ||
# @!attr_reader :config | ||
# @return [Hash<String, Object>] | ||
# @!attr_reader :name | ||
# @return [#to_sym] | ||
attr_reader :config, :name | ||
|
||
## | ||
# @param [#to_sym] name | ||
# @param [Hash<String, Object>] config | ||
def initialize(name, config) | ||
@config = config | ||
@name = name.to_sym | ||
end | ||
|
||
## | ||
# @return [Hash{Symbol => Object}] | ||
def form_options | ||
config.fetch('form', {}).symbolize_keys | ||
end | ||
|
||
## | ||
# @return [Enumerable<Symbol>] | ||
def index_keys | ||
config.fetch('indexing', []).map(&:to_sym) | ||
end | ||
|
||
## | ||
# @return [Dry::Types::Type] | ||
def type | ||
collection_type = if config['multi_value'] | ||
Valkyrie::Types::Array.constructor { |v| Array(v).select(&:present?) } | ||
else | ||
Identity | ||
end | ||
collection_type.of(type_for(config['type'])) | ||
end | ||
|
||
## | ||
# @api private | ||
# | ||
# This class acts as a Valkyrie/Dry::Types collection with typed members, | ||
# but instead of wrapping the given type with itself as the collection type | ||
# (as in `Valkyrie::Types::Array.of(MyType)`), it returns the given type. | ||
# | ||
# @example | ||
# Identity.of(Valkyrie::Types::String) # => Valkyrie::Types::String | ||
# | ||
class Identity | ||
## | ||
# @param [Dry::Types::Type] | ||
# @return [Dry::Types::Type] the type passed in | ||
def self.of(type) | ||
type | ||
end | ||
end | ||
|
||
private | ||
|
||
## | ||
# Maps a configuration string value to a `Valkyrie::Type`. | ||
# | ||
# @param [String] | ||
# @return [Dry::Types::Type] | ||
def type_for(type) | ||
case type | ||
when 'id' | ||
Valkyrie::Types::ID | ||
when 'uri' | ||
Valkyrie::Types::URI | ||
when 'date_time' | ||
Valkyrie::Types::DateTime | ||
else | ||
"Valkyrie::Types::#{type.capitalize}".constantize | ||
end | ||
end | ||
end | ||
|
||
class UndefinedSchemaError < ArgumentError; end | ||
|
||
private | ||
|
||
## | ||
# @param [#to_s] schema_name | ||
# @return [Enumerable<AttributeDefinition] | ||
def definitions(schema_name, version) | ||
Hyrax::FlexibleSchema.find_by(version: version).attributes_for(schema_name).map do |name, config| | ||
AttributeDefinition.new(name, config) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.