primalize icon indicating copy to clipboard operation
primalize copied to clipboard

Add simple validation DSL

Open jgaskins opened this issue 7 years ago • 0 comments

Following a conversation on The Practical Dev, I began thinking that maybe validations on the output aren't a terrible idea. If the contract between an API and a client says that some number will be a float in the range of 0.0...1.0, checking that it's an instance of Float is not good enough to comply with that contract.

This PR (in its current state) is an example of how declaring that could look:

class PostPrimalizer < Primalize::Single
  attributes(
    upvote_percentage: validate(float) { |percentage| (0...1).cover? percentage },
  )
end

A few things I'm unsure of:

  • Naming of validate. It is a validation, but so are the type and structure checks. This is intended for the value of primitives, but that's really the only difference.
  • The block has a different meaning here than for the other DSL methods. It's a pass/fail depending on truthiness of the return value rather than transforming what it receives. It makes sense with that context, but divergence from the convention feels weird.
  • Error messages can't be as nice as for other DSL methods because we can't show why it failed validation, just that it did.

The only thing I can think of to improve on these is to make it work something like this:

attributes(
  number: value(integer, between: 0..10),
  email: value(string, match: /\w@\w/),
)

That means we have to define a bunch of special-case matchers, but it would let the error messages look good, we wouldn't have to have a different meaning for the block, and it's also another naming suggestion for the DSL method.

jgaskins avatar Feb 18 '18 21:02 jgaskins