Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Feb 16 23:37
    asoules starred dry-rb/dry-system
  • Feb 16 20:37

    dry-bot on master

    [devtools] sync (compare)

  • Feb 16 20:37

    flash-gordon on master

    Update CHANGELOG (compare)

  • Feb 16 20:36

    flash-gordon on v1.3.1

    (compare)

  • Feb 16 20:34

    dry-bot on master

    [devtools] sync (compare)

  • Feb 16 20:33

    flash-gordon on master

    Fix version number (compare)

  • Feb 16 20:32

    dry-bot on master

    [devtools] sync (compare)

  • Feb 16 20:32

    flash-gordon on master

    Update CHANGELOG (compare)

  • Feb 16 20:27

    flash-gordon on master

    Bump version to 1.3.1 (compare)

  • Feb 16 20:26

    flash-gordon on impove-predicate-inferrer

    (compare)

  • Feb 16 20:26

    flash-gordon on master

    Infer hash? predicate for hash … Merge pull request #395 from dr… (compare)

  • Feb 16 20:26
    flash-gordon closed #395
  • Feb 16 20:26
    dry-bot commented #395
  • Feb 16 20:24
    flash-gordon opened #395
  • Feb 16 20:23

    flash-gordon on impove-predicate-inferrer

    Infer hash? predicate for hash … (compare)

  • Feb 16 17:48
    Quenedi starred dry-rb/dry-types
  • Feb 16 15:58
    ewertoncodes starred dry-rb/dry-types
  • Feb 15 18:04
    gmcabrita starred dry-rb/dry-auto_inject
  • Feb 15 18:04
    gmcabrita starred dry-rb/dry-equalizer
  • Feb 15 18:04
    gmcabrita starred dry-rb/dry-initializer
Gregory Huczynski
@greghuc

Hi @solnic + dry-validation folks.

How does dry-validation play with normalisation of inputs before validation?

For example, I've a JSON rest-api 'post message' endpoint that takes an email and message as input. For api flexibility, I currently trim whitespace from the email value before 'proper' validation (does value match email regex?). So it feels like a two stage process:

I think dry-validation lets me do the validation/coercion part. But how does it fit with the normalisation part? I only want to normalise user inputs I don't control. I wouldn't do this loading an email-serialised-as-string from the DB: would just do Coercion of String(“hello@example.com”) -> Email(“hello@example.com”)

Thanks - trying to make my first baby steps with dry-validation and dry-types :-)

Piotr Solnica
@solnic
well, it's the old story of initial cost vs long-term cost
we can (and will) have batteries-included gems that work with rom-rb etc. but they will be 1) simpler 2) extendible w/o monkey-patches
Fran Worley
@fran-worley
@solnic I still thank myself that I never went down the devise route. Unfortunately I did get sucked into CanCan for authorisation which is proving to be very difficult to unwind...
Piotr Solnica
@solnic
so ie I'm not interested in building things like devise, it's too big, too complex, from my experience devise was one of the biggest reasons why upgrading a rails app to new rails was close-to-impossible (as in, it'd be very risky and time consuming)
I've never seen an auth system with built-in ACL that was done right, not sure if it's even feasible to do haha
Fran Worley
@fran-worley
@solnic I reached the same conclusion. Dependencies like carrierwave and cancan have caused me so many headaches.
Piotr Solnica
@solnic
@greghuc hey Greg, you can define custom types with custom coercion logic, see here for an example
they can carry not only coercion logic but also constraints that will be used for validation (if you want to)
@fran-worley there are two reasons for that, first of all massive inheritence-based APIs, rather than having re-usable objects gems provided mixins or abstract classes (or both), secondly gems doing too much :)
@greghuc default behavior is to sanitize input based on key definitions and value type definitions, but sneaking in normalization is totally fine, I think it's gonna work well for you. We're currently working on 0.8.0 releases of types and validation so if you see something odd, just report an issue. We want to get to 1.0.0 asap so feedback is very welcome :)
Gregory Huczynski
@greghuc

Hi @solnic, thanks for feedback. So am I looking at:

  • JSON API input: dry-validation used to consume " hello@example.com " and return StrippedString("hello@example.com")
  • In domain world, have "Message" object (email + message attributes): dry-types used to represent email with Email type (i.g. string that matches regex). An Email type can be constructed from normal String or StrippedString

I am unclear at which point the supplied 'email' API input value gets converted into an Email type: at the end of input validation, or only when passed into domain "Message" object

Piotr Solnica
@solnic
@greghuc oh so you want to coerce a string into a custom type too?
personally I'd advocate against doing so, because you'd be using a validation schema also as a data-to-object-mapper, this is too much. I'd recommend focusing on pure data validation and then using something like a dry-type Struct to build a domain object from safe-and-clean data
structs from dry-types can build objects from hashes so you've got everything you need
Gregory Huczynski
@greghuc

@solnic I'm feeling my way forward on a web-app refactor.

I'm wondering about using some custom types in my domain objects. The only custom types that make sense are for Email and Url, and that's really regex enforcement, and ensuring lowercase (Email("hi@example.com == "HI@eXample.com"). Everything else is likely fine in normal ruby types.

But I'm still trying to work out the JSON API input end: that's what requires some extra normalisation. If I'm loading Email or Url types from the DB, I wouldn't need the normalisation, but I would still want to do regex enforcement and lowercasing, which would be encapsulated in the the custom types

Regarding "you'd be using a validation schema also as a data-to-object-mapper, this is too much". It's a hard one to call: I presume dry-validation can coerce a String into a DateTime? That looks a lot like data-to-object mapping ;-)
Gregory Huczynski
@greghuc
@solnic I think my underlying issue is how dry-validation and dry-types fit into a web-app (JSON DB-backed API in my case). I kind of want there to be two separate parts:
  • Input validation + coercion: takes user input, normalises it and coerces into simple base types (String, DateTime, and custom types like Url and Email), and returns a hash of these typed attributes. Or errors. dry-validation might do this.
  • Immutable, typed domain objects: a domain object is defined as a set of typed attributes. The object is either constructed from validated-input-hash, or from hash-loaded-from-database. Though hash-loaded-from-database may have had some type coercion (i.e. email stored as string in DB becomes Email type), or that type coercion is built into the domain object. dry-types might work for this
Got to go - back later!
Piotr Solnica
@solnic
:laughing:
@greghuc yeah but we're still dealing with ruby primitives
require 'dry-validation'

class Email
  attr_reader :value

  def self.new(input)
    super("#{input}.com")
  end

  def initialize(value)
    @value = value
  end
end

Dry::Types.register_class(Email)

schema = Dry::Validation.Form do
  key(:email).required(type?: Email)
end

puts schema.('email' => 'jane@doe').inspect
@greghuc ^^
output:
#<Dry::Validation::Result output={:email=>#<Email:0x007fe6f2353370 @value="jane@doe.com">} messages={}>
Fran Worley
@fran-worley
@solnic is my assumption here correct?
When a predicate is curried, we can get some, all or none of the argument values. The same happens when it is called so we can't make any assumptions about what args we receive and when.
Piotr Solnica
@solnic
@fran-worley yeah, you don't know if you've got all args, there's no mechanism for that (at least not yet)
Fran Worley
@fran-worley
@solnic think I might have to add that as otherwise I'll be overriding an intentional nil.
Piotr Solnica
@solnic
@fran-worley I believe this will turn out to be useful in many places, so feel free to add it
it's a matter of storing arity
ah, failing specs first in dry-rb/dry-logic#13 nice :)
it's easier to TDD when mostly you care about inputs/outputs right? :)
Fran Worley
@fran-worley
@solnic thats my plan. What do you think about the AST change?
Piotr Solnica
@solnic
I like it, this is a pretty useful piece of info
we're gonna allocate more arrays but that shouldn't hurt esp that we can simplify code in dry-v thanks to this change
Fran Worley
@fran-worley
I don't think we can loose the input value from the result ast just yet as it isn't always exactly the same. but for error messages in dry-v it means that you can just focus on the predicate part as that has all the info including the input
Piotr Solnica
@solnic
right, the result part of dry-logic is the complicated part
I hope we can improve this over time
I esp don't like that we evaluate input two times :(
Fran Worley
@fran-worley
and when you recreate the predicate it causes all sorts of issues as I keep loosing the argument names...
Piotr Solnica
@solnic
wow wait, wdym by 'recreate predicate'?
Fran Worley
@fran-worley
When you call predicate.curry it intern calls Predicate.new passing in the curried version as the block
Therefore it's not enough to get the argument names on initialisation as calling block.parameters after it has been curried simply returns :rest not the actual parameters
Piotr Solnica
@solnic
ah shit
yeah that's what I'm talking about when I say that it'd be great to see MRI getting better FP features rather than some rails-inspired nonsenses
Gregory Huczynski
@greghuc
@solnic thanks for the code. Will start on API refactor with dry-validation and dry-type soon.
Piotr Solnica
@solnic
well, we have no other choice than to extend predicate with options and store needed data there
Fran Worley
@fran-worley
@solnic thats what I figured is it a significant performance hit?