Segmenting predicates


#1

I’m trying to achieve something like the following:

module CommonPredicates
  include Dry::Logic::Predicates

  predicate(:foo?) do |value|
    ! value.nil?
  end
end

module MyPredicates
  include Dry::Logic::Predicates

  predicate(:email?) do |value|
    ! /magical-regex-that-matches-emails/.match(value).nil?
  end
end

schema = Dry::Validation.Schema do
  configure do
    predicates(CommonPredicates)
    predicates(MyPredicates)

    # the second 'predicates(...)' overwrites the first one

  end

  required(:email).filled(:foo?, :email?)
end

I’ve tried every way I can think of (although I will admit being a newbie with dry-validation). I’m using dry-validation to validate user input.

Thanks in advance…

– sw


#2

Hi @stevewi. This happens because predicate modules are used as simple containers of methods. These predicates are resolved using D::V::PredicateRegistry. D::V::Schema#predicates is responsible for populating this registry. It doesn’t merge new predicates into the predicates set before, it just replaces them:

I had a similar problem so I came up with this workaround (the topic didn’t get much attention though). Basically, it employs modules which define predicates when included in the schema.

I use this workaround in production but I’m not happy with it, because I believe it has too much knowledge of the inner workings of the gem for an external “plugin”.