dry-rb / dry-validation

Validation library with type-safe schemas and rules
https://dry-rb.org/gems/dry-validation
MIT License
1.34k stars 188 forks source link

Macros do not support validation on root object #688

Open midnight-wonderer opened 3 years ago

midnight-wonderer commented 3 years ago

Describe the bug

I extracted a macro into a reusable module, like this:

module ReusableRule
  extend ::ActiveSupport::Concern

  included do
    register_macro(:reusable_macro) do
      # do some validations here 
    end
  end
end

and use it like this:

class SomeContracr < ::Dry::Validation::Contract
  params do
    # define some params here
  end

  include ::ReusableRule
  rule(path_to: :inner_hash).validate(:reusable_macro)
end

which works fine.

But I cannot use it on the root hash, like this:

class SomeContracr < ::Dry::Validation::Contract
  params do
    # define some params here
  end

  include ::ReusableRule
  rule.validate(:reusable_macro)
end

Expected behavior

The macro should validate the root hash the same way as when I use it on an inner hash.

Actual behavior

dry-validation throws an ArgumentError

lib/dry/validation/values.rb:59:in `[]': +key+ must be a valid path specification (ArgumentError)

My environment

Suggestion

Probably adding

return data if args.size < 1

around here.

midnight-wonderer commented 3 years ago

Oops! my bad I can avoid the error myself by detecting keys.empty? in my macro.

resolved_value, base_path = if keys.empty?
  [values.data, []]
else
  [value, path.keys]
end
# use resolved_value and base_path for validations

If I call value as I described initially, the error will be triggered.

I'll leave this thread open and let the maintainer decide whether the inconsistencies are something to be handled by dry-rb, or by consumers. I would understand if there is no good solution for the library, though. Feel free to close the thread if that is the case.