dry-rb / dry-logic

Predicate logic with rule composition
https://dry-rb.org/gems/dry-logic/
MIT License
179 stars 66 forks source link

How do I create custom predicates? #53

Closed radar closed 5 years ago

radar commented 5 years ago

I'm currently attempting to create custom predicates by writing this code:

require 'dry-validation'

module Predicates
  include Dry::Logic::Predicates

  predicate(:uuid?) do |value|
    !Types::UUID_REGEX.match(value.to_s).nil?
  end
end

class BaseContract < Dry::Validation::Contract
  include Predicates

  params do
    required(:aggregate_id)
    required(:section_id).filled(:uuid?)
  end
end

However, this code raises an exception:

dry-schema-0.5.1/lib/dry/schema/trace.rb:104:in `method_missing': uuid? predicate is not defined (ArgumentError)

What am I doing wrong here?

I couldn't find any documentation for this in dry-validation, or dry-logic.

Gemfile

source 'https://rubygems.org'

gem 'dry-validation', '1.0.0.beta2'

Gemfile.lock

GEM
  remote: https://rubygems.org/
  specs:
    concurrent-ruby (1.1.5)
    dry-configurable (0.8.2)
      concurrent-ruby (~> 1.0)
      dry-core (~> 0.4, >= 0.4.7)
    dry-container (0.7.0)
      concurrent-ruby (~> 1.0)
      dry-configurable (~> 0.1, >= 0.1.3)
    dry-core (0.4.7)
      concurrent-ruby (~> 1.0)
    dry-equalizer (0.2.2)
    dry-inflector (0.1.2)
    dry-initializer (2.5.0)
    dry-logic (0.6.1)
      concurrent-ruby (~> 1.0)
      dry-core (~> 0.2)
      dry-equalizer (~> 0.2)
    dry-schema (0.5.1)
      concurrent-ruby (~> 1.0)
      dry-configurable (~> 0.8, >= 0.8.0)
      dry-core (~> 0.2, >= 0.2.1)
      dry-equalizer (~> 0.2)
      dry-initializer (~> 2.4)
      dry-logic (~> 0.6, >= 0.6.0)
      dry-types (~> 0.15, >= 0.15.0)
    dry-types (0.15.0)
      concurrent-ruby (~> 1.0)
      dry-container (~> 0.3)
      dry-core (~> 0.4, >= 0.4.4)
      dry-equalizer (~> 0.2, >= 0.2.2)
      dry-inflector (~> 0.1, >= 0.1.2)
      dry-logic (~> 0.5, >= 0.5)
    dry-validation (1.0.0.beta2)
      concurrent-ruby (~> 1.0)
      dry-core (~> 0.2, >= 0.2.1)
      dry-equalizer (~> 0.2)
      dry-initializer (~> 2.5)
      dry-schema (~> 0.5, >= 0.5)

PLATFORMS
  ruby

DEPENDENCIES
  dry-validation (= 1.0.0.beta2)

BUNDLED WITH
   2.0.1
solnic commented 5 years ago

If you need uuid? I would actually accept a PR that adds it (see https://github.com/dry-rb/dry-logic/issues/43)

In general, custom predicates will be discouraged in dry-validation 1.0.0 because schemas should be used for simple checks and rule should be used for other, for domain-specific validations.

radar commented 5 years ago

Thanks @solnic.

So just to double check: we should definitely be using rules here instead of new predicates?

radar commented 5 years ago

I’ve looked at #43 and the uuid-tools gem and the gem’s code is scary byte stuff with Ruby that I don’t want to tinker with. Braver souls might prevail.

solnic commented 5 years ago

So just to double check: we should definitely be using rules here instead of new predicates?

For a type-check like uuid? I would say a predicate makes sense but ie for checking if the value is unique (in the db sense) it should be a rule.

I’ve looked at #43 and the uuid-tools gem and the gem’s code is scary byte stuff with Ruby that I don’t want to tinker with. Braver souls might prevail.

Yeah UUIDs are actually more complex than some people may think 😄 Maybe we could add a simple regex-based check to cover the common case.