Skip to content

Commit

Permalink
Update Dry-Struct/Dry-Types.
Browse files Browse the repository at this point in the history
This should add all the necessary back-ports to prevent having to
release a major version of Valkyrie, but still support the latest
dry-types and dry-struct.
  • Loading branch information
tpendragon committed Jul 5, 2018
1 parent 75b26fe commit 36754fa
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def ordered_list
class NestedProperty < ::Valkyrie::ValueMapper
FedoraValue.register(self)
def self.handles?(value)
value.is_a?(Property) && value.value.is_a?(Hash) && value.value[:internal_resource]
value.is_a?(Property) && (value.value.is_a?(Hash) || value.value.is_a?(Valkyrie::Resource)) && value.value[:internal_resource]
end

def result
Expand Down
2 changes: 1 addition & 1 deletion lib/valkyrie/persistence/memory/query_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def find_by(id:)
def find_by_alternate_identifier(alternate_identifier:)
alternate_identifier = Valkyrie::ID.new(alternate_identifier.to_s) if alternate_identifier.is_a?(String)
validate_id(alternate_identifier)
cache.select { |_key, resource| resource['alternate_ids'].include?(alternate_identifier) }.values.first || raise(::Valkyrie::Persistence::ObjectNotFoundError)
cache.select { |_key, resource| resource[:alternate_ids].include?(alternate_identifier) }.values.first || raise(::Valkyrie::Persistence::ObjectNotFoundError)
end

# @param ids [Array<Valkyrie::ID, String>] The IDs to query for.
Expand Down
2 changes: 1 addition & 1 deletion lib/valkyrie/persistence/solr/model_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def result
class NestedObjectValue < ::Valkyrie::ValueMapper
SolrMapperValue.register(self)
def self.handles?(value)
value.value.is_a?(Hash)
value.value.is_a?(Hash) || value.value.is_a?(Valkyrie::Resource)
end

def result
Expand Down
48 changes: 39 additions & 9 deletions lib/valkyrie/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,39 @@ module Valkyrie
# @see lib/valkyrie/specs/shared_specs/resource.rb
class Resource < Dry::Struct
include Draper::Decoratable
constructor_type :schema
def self.constructor_type(type)
raise unless type == :schema
warn "[DEPRECATION] constructor_type has been removed by dry-struct and will be removed in the next " \
"major release of Valkyrie. Please use transform_types and transform_keys. " \
"This method will raise if you try an argument other than the supported :schema, " \
"and implements a replacement for :schema in the base class. You should be able to " \
"delete this line of code." \
"See https://github.com/dry-rb/dry-struct/releases/tag/v0.5.0." \
"Called from #{Gem.location_of_caller.join(':')}"
allow_nonexistent_keys
end

# Allows a Valkyrie::Resource to be instantiated without providing every
# available key, and makes sure the defaults are set up if no value is
# given.
def self.allow_nonexistent_keys
transform_types { |t| t.meta(omittable: true) }
nil_2_undef = ->(v) { v.nil? ? Dry::Types::Undefined : v }
transform_types do |type|
type = type.meta(omittable: true)
if type.default?
type.constructor(nil_2_undef)
else
type
end
end
end

# Overridden to provide default attributes.
# @note The current theory is that we should use this sparingly.
def self.inherited(subclass)
super(subclass)
subclass.constructor_type :schema
subclass.allow_nonexistent_keys
subclass.attribute :internal_resource, Valkyrie::Types::Any.default(subclass.to_s)
subclass.attribute :created_at, Valkyrie::Types::DateTime.optional
subclass.attribute :updated_at, Valkyrie::Types::DateTime.optional
Expand All @@ -41,7 +67,7 @@ def self.fields
# {Valkyrie::Types::Set}
def self.attribute(name, type = Valkyrie::Types::Set.optional)
define_method("#{name}=") do |value|
instance_variable_set("@#{name}", self.class.schema[name].call(value))
@attributes[name] = self.class.schema[name].call(value)
end
super
end
Expand All @@ -62,11 +88,6 @@ def self.human_readable_type=(val)
@_human_readable_type = val
end

# @return [Hash] Hash of attributes
def attributes
to_h
end

# @param name [Symbol] Attribute name
# @return [Boolean]
def has_attribute?(name)
Expand All @@ -82,13 +103,22 @@ def column_for_attribute(name)

# @return [Boolean]
def persisted?
@new_record == false
new_record == false
end

def to_key
[id]
end

def [](name)
unless name.is_a?(Symbol)
warn "[DEPRECATION] #[] only accepts symbol arguments in dry-struct now. Support for string arguments " \
"will be removed in the next major release of Valkyrie. Please use symbols. " \
"Called from #{Gem.location_of_caller.join(':')}"
end
super(name.to_sym)
end

def to_param
to_key.map(&:to_s).join('-')
end
Expand Down
12 changes: 11 additions & 1 deletion lib/valkyrie/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,17 @@ def of(type)
end

def member(type)
super.default([].freeze)
warn "[DEPRECATION] .member has been removed by dry-types and will be removed in the next " \
"major version of Valkyrie. Please use .of instead. " \
"Called from #{Gem.location_of_caller.join(':')}"
of(type).default([].freeze)
end

# Override optional to provide a default because without it an
# instantiated Valkyrie::Resource's internal hash does not have values for
# every possible attribute, resulting in `MissingAttributeError`.
def optional
super.default(nil)
end
end
Array.singleton_class.include(ArrayDefault)
Expand Down
23 changes: 23 additions & 0 deletions spec/valkyrie/resource_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,29 @@ class Resource < Valkyrie::Resource
end
end

describe ".constructor_type" do
it "throws a deprecation warning" do
allow(Resource).to receive(:warn)

Resource.constructor_type :schema
expect(Resource).to have_received(:warn)
end
end

describe "[]" do
it "works as an accessor for properties" do
expect(resource[:title]).to eq []
end
it "throws a deprecation warning if accessed via a string" do
# rubocop:disable RSpec/SubjectStub
allow(resource).to receive(:warn)
# rubocop:enable RSpec/SubjectStub
expect(resource["title"]).to eq []

expect(resource).to have_received(:warn)
end
end

describe "#has_attribute?" do
it "returns true for fields that exist" do
expect(resource.has_attribute?(:title)).to eq true
Expand Down
4 changes: 2 additions & 2 deletions spec/valkyrie/types_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ class Resource < Valkyrie::Resource
attribute :authors, Valkyrie::Types::Array
attribute :geonames_uri, Valkyrie::Types::URI
attribute :thumbnail_id, Valkyrie::Types::ID
attribute :embargo_release_date, Valkyrie::Types::Set.member(Valkyrie::Types::DateTime).optional
attribute :embargo_release_date, Valkyrie::Types::Set.of(Valkyrie::Types::DateTime).optional
attribute :set_of_values, Valkyrie::Types::Set
attribute :my_flag, Valkyrie::Types::Bool
attribute :nested_resource_array, Valkyrie::Types::Array.member(Resource.optional)
attribute :nested_resource_array_of, Valkyrie::Types::Array.of(Resource.optional)
attribute :nested_resource_set, Valkyrie::Types::Set.member(Resource.optional)
attribute :nested_resource_set, Valkyrie::Types::Set.of(Resource.optional)
end
end
after do
Expand Down
2 changes: 1 addition & 1 deletion valkyrie.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'dry-struct'
spec.add_dependency 'draper'
spec.add_dependency 'activemodel'
spec.add_dependency 'dry-types', '~> 0.12.0'
spec.add_dependency 'dry-types', '~> 0.13.0'
spec.add_dependency 'rdf'
spec.add_dependency 'active-fedora'
spec.add_dependency 'activesupport'
Expand Down

0 comments on commit 36754fa

Please sign in to comment.