How can I use an external dependency in a dynamic predicate argument?

I’m using dry-validations 0.13.3 with Ruby 2.6.2. I’ve attempted to combine external dependencies with dynamic predicates:

schema = Dry::Validation.Schema do
  configure do
    option :my_collection

    def part_of_collection
      my_collection.values
    end
  end

  required(:the_thing).value(included_in?: part_of_collection)
end

schema.with(my_collection: { alpha: 1, beta: 2 }).call({ the_thing: 42 })

Unfortunately, it looks like my_collection always returns nil:

NoMethodError: undefined method `value' for nil:NilClass
from repro.rb:6:in `part_of_collection'

It does work to access the external dependency in a custom predicate:

schema = Dry::Validation.Schema do
  configure do
    option :my_collection

    def part_of_collection?(v)
      my_collection.values.include? v
    end
  end

  required(:the_thing).value(:part_of_collection?)
end

schema.with(my_collection: { alpha: 1, beta: 2 }).call({ the_thing: 42 })

Unfortunately, this requires me to define my own messages for my custom predicate:

Dry::Validation::MissingMessageError: message for part_of_collection? was not found

Is there a trick I’m missing?

It is not possible to pass a dynamic list of allowed values to included_in? but it’s not specific to dry-validation, it’s how ruby works. For that, you’ll need one more level of indirection as you have in the second example where invocation of :part_of_collection? is postponed until validation is run. In any case, this type of rules were removed in dry-validation 1.0 and replaced with a more powerful and flexible approach, I suggest you upgrading to 1.x.

Could you expand on this? This is literally an example from the documentation section titled Dynamic Predicate Arguments:

DataSchema = Dry::Validation.Schema do
  configure do
    def data
      %w(a b c)
    end
  end

  required(:letter).filled(included_in?: data)
end

I’d love to, but we are currently attempting to move from Reform to Dry, but our existing usage of Reform requires Dry 0.13. Once we have replaced Reform with Dry, then we can upgrade.

Could you give an example (or point to some docs) for how that would be done in 1.0? It will be good to know for when we get there.

Could you expand on this? This is literally an example from the documentation section titled Dynamic Predicate Arguments:

Well, good point and mb dry-v 0.x adds indirection there automatically, never tried it so honestly don’t know what’s the cause of the error.

Could you give an example (or point to some docs) for how that would be done in 1.0? It will be good to know for when we get there.

Normally, via a contract option + a rule:

Class.new(Dry::Validation::Contract) do
  option :my_collection

  schema do
    required(:the_thing).value(:integer)
  end

  rule(:the_thing) do
    key.failure('not in collection') unless my_collection.include?(value)
  end
end