These are chat archives for dry-rb/chat

20th
Jun 2016
Oskar Szrajer
@gotar
Jun 20 2016 06:51
hmm something changed in dry-validator? this code start throwing WARN
    CommentSchema = Dry::Validation.Form do
      required(:post_id).filled(:int?)
      required(:body).filled(:str?)
    end

 WARN -- : Missing type spec for :post_id key
how to define type and what its doing? I was sure those filled(:int?) determine type of it
Oskar Szrajer
@gotar
Jun 20 2016 06:57
ok found it:
    CommentSchema = Dry::Validation.Form do
      required(:post_id, :int).filled
      required(:body, :str).filled
    end
Oskar Szrajer
@gotar
Jun 20 2016 07:48
ps is there anywhere some basic example of dry-view?
Tim Riley
@timriley
Jun 20 2016 08:13
@gotar we use dry-view in icelab/berg
And how we integrate it there is identical to how we do it in our (private) client apps, so that’d be a decent example.
I hope to actually extract some of those things out into a gem for easy reuse.
Piotr Solnica
@solnic
Jun 20 2016 08:16
@gotar we're moving away from inferring coercions from predicates to explicit type specs
Oskar Szrajer
@gotar
Jun 20 2016 08:19
@timriley Yeap I saw your way of using it, I saw extra plugins there used, was looking for very basic exmaple to show during workshops
Tim Riley
@timriley
Jun 20 2016 08:20
I guess in that case it’d be just a view class and a template and my_view.(), right?
Depends on how much functionality you want to offer. You need to add some of that extra stuff in if you want flash messages, common helpers, etc.
Another option would be to eschew dry-view for the workshop and just use roda’s view rendering. Depends on how much stuff you want to include.
Fran Worley
@fran-worley
Jun 20 2016 08:29
@solnic what do you do with Forms where you want an array of integers? When coercion was inferred you could just do required(:foo).each(:int?). This now fails because in a form each element will always be a string and no coercion happens...
Oskar Szrajer
@gotar
Jun 20 2016 08:29
Hmm i will stick with roda view and maybe you inform about dry-view
Fran Worley
@fran-worley
Jun 20 2016 08:29
my schema:
Dry::Validation.Form do
  configure { config.type_specs = true }

  required(:foo, :array).each(:int?)
end
Piotr Solnica
@solnic
Jun 20 2016 08:31
@fran-worley forgot about this use-case
maybe we could have required(:foo, [:int])
Tim Riley
@timriley
Jun 20 2016 08:32
That’s a bit like how Swift does type declarations ^
It’d mean we’d need to splat the args for normal situations – is that what you decide to do, @solnic?
Piotr Solnica
@solnic
Jun 20 2016 08:33
we already do it like that for each inside nested schemas, but I forgot to cover the root-level schema
not sure tbh
Fran Worley
@fran-worley
Jun 20 2016 08:34
or a hash required(:foo, array: :int) , required(:foo, array: :string), required(:foo, array: :date)
Piotr Solnica
@solnic
Jun 20 2016 08:35
yeah that would be more clear I think
Fran Worley
@fran-worley
Jun 20 2016 08:35
But it should be the same as nested schemas or people will get double confused
Piotr Solnica
@solnic
Jun 20 2016 08:35
no no, I mean that I used [:int] convention “under the hood” in nested schemas
Fran Worley
@fran-worley
Jun 20 2016 08:35
oooohh ok :)
Fran Worley
@fran-worley
Jun 20 2016 08:36
well in that case we could just have required(:foo, array: :int) convert down to [:int] under the hood
Piotr Solnica
@solnic
Jun 20 2016 08:37
@gotar btw this warning should be displayed only when type_specs = true is set in config, I shall fix that
Fran Worley
@fran-worley
Jun 20 2016 08:38
@solnic will that setting get turned on by default at some point?
Piotr Solnica
@solnic
Jun 20 2016 08:38
in 1.0 it will be default behavior and the setting will be removed
we just need to transition people to explicit type specs along the way
I actually think we will end up with the double-schema approach we’ve been discussing as the recommended usage pattern
so 1) define a basic coercion/type-check schema 2) infer domain-validation schema on from the basic one
Fran Worley
@fran-worley
Jun 20 2016 08:40
I prefer that personally
Piotr Solnica
@solnic
Jun 20 2016 08:40
the former would be used in the http layer
the latter in the app layer
this way 0 (zero) http concerns would leak into app layer
Fran Worley
@fran-worley
Jun 20 2016 08:40
Awesome
Piotr Solnica
@solnic
Jun 20 2016 08:41
we could build a rack middleware that handles that, so you define your schemas for each http end-point and params sent to “action handlers” (whatever they are) would be already coerced properly
so your app’s validation would only be triggered when types are correct
this would put even more emphasis on type safety as a first class concern
Tim Riley
@timriley
Jun 20 2016 08:42
:+1: :+1: :+1:
Tim Riley
@timriley
Jun 20 2016 08:45
oh that’s interesting. may be a nicer fit than going to rust for performance.
John Backus
@backus
Jun 20 2016 09:16
Trying to update to the dry-v on master
$ cat Gemfile.lock | grep dry-
  remote: https://github.com/dry-rb/dry-logic.git
    dry-logic (0.2.3)
      dry-container (~> 0.2, >= 0.2.6)
      dry-equalizer (~> 0.2)
  remote: https://github.com/dry-rb/dry-types.git
    dry-types (0.7.2)
      dry-configurable (~> 0.1)
      dry-container (~> 0.3)
      dry-equalizer (~> 0.2)
      dry-logic (~> 0.2, >= 0.2.3)
      dry-monads (>= 0.0.1)
  remote: https://github.com/dry-rb/dry-validation.git
    dry-validation (0.7.4)
      dry-configurable (~> 0.1, >= 0.1.3)
      dry-container (~> 0.2, >= 0.2.8)
      dry-equalizer (~> 0.2)
      dry-logic (~> 0.2, >= 0.2.3)
      dry-types (~> 0.7, >= 0.7.2)
    dry-configurable (0.1.6)
    dry-container (0.3.4)
      dry-configurable (~> 0.1, >= 0.1.3)
    dry-equalizer (0.2.0)
    dry-monads (0.0.1)
  dry-logic!
  dry-types!
  dry-validation!
$ cat test.rb
require 'dry/validation'

module MyPredicates
  include Dry::Logic::Predicates

  predicate(:email?) do |value|
    value.include?('@')
  end
end

Dry::Validation.Schema do
  configure do
     config.predicates = MyPredicates
  end

  required(:email).value(:email?)
end
$ bundle exec ruby test.rb
W, [2016-06-20T02:15:26.224832 #96395]  WARN -- : Missing type spec for :email key [test.rb line 16]
/Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/predicate_registry.rb:93:in `raise_unknown_predicate_error': +email?+ is not a valid predicate name (ArgumentError)
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/predicate_registry.rb:86:in `ensure_valid_predicate'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/schema/value.rb:142:in `predicate'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/schema/value.rb:148:in `node'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/schema/rule.rb:179:in `key'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/schema/rule.rb:167:in `block in infer_predicates'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/schema/rule.rb:161:in `map'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/schema/rule.rb:161:in `infer_predicates'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation/schema/rule.rb:82:in `value'
  from test.rb:16:in `block in <main>'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation.rb:28:in `instance_exec'
  from /Users/johnbackus/.rvm/gems/ruby-2.3.1/bundler/gems/dry-validation-511cf7f29945/lib/dry/validation.rb:28:in `Schema'
  from test.rb:11:in `<main>'
Am I doing something wrong?
Fran Worley
@fran-worley
Jun 20 2016 09:17
@backus you will probably run into issues with dependencies (dry-logic, dry-types) which also must be on master
John Backus
@backus
Jun 20 2016 09:18
Ah so I bumped dry-logic to point to master for this
Does dry-types have to be on the most recent master also?
I tried to dump my dry-* dependencies above but it didn't work great. This should represent what revisions I'm on:
$ ag 'dry-' -A1 Gemfile.lock
  remote: https://github.com/dry-rb/dry-logic.git
  revision: 8f8dffb9d857a47d09b380e733cf98a0eb814ab6
    dry-logic (0.2.3)
      dry-container (~> 0.2, >= 0.2.6)
      dry-equalizer (~> 0.2)

  remote: https://github.com/dry-rb/dry-types.git
  revision: cc020500b4aec5dab2fca51e275e1bf51e2ed3be
    dry-types (0.7.2)
      concurrent-ruby (~> 1.0)
      dry-configurable (~> 0.1)
      dry-container (~> 0.3)
      dry-equalizer (~> 0.2)
      dry-logic (~> 0.2, >= 0.2.3)
      dry-monads (>= 0.0.1)
      ice_nine (~> 0.11)
  remote: https://github.com/dry-rb/dry-validation.git
  revision: 511cf7f299459d52bd32d3a2e0cb150dfd580359
    dry-validation (0.7.4)
      concurrent-ruby (~> 1.0)
      dry-configurable (~> 0.1, >= 0.1.3)
      dry-container (~> 0.2, >= 0.2.8)
      dry-equalizer (~> 0.2)
      dry-logic (~> 0.2, >= 0.2.3)
      dry-types (~> 0.7, >= 0.7.2)

    dry-configurable (0.1.6)
      concurrent-ruby (~> 1.0)
    dry-container (0.3.4)
      concurrent-ruby (~> 1.0)
      dry-configurable (~> 0.1, >= 0.1.3)
    dry-equalizer (0.2.0)
    dry-monads (0.0.1)
    equalizer (0.0.11)
  dry-logic!
  dry-types!
  dry-validation!
  guard (~> 2.14)
@fran-worley ^
I'll try to see if it reproduces in a fresh project
Andy Holland
@AMHOL
Jun 20 2016 09:25
@backus try:
require 'dry/validation'

module MyPredicates
  include Dry::Logic::Predicates

  predicate(:email?) do |value|
    value.include?('@')
  end
end

Dry::Validation.Schema do
  configure do
     config.predicates = MyPredicates
  end

  required(:email, :str).value(:email?)
end
See dry-rb/dry-validation#189
John Backus
@backus
Jun 20 2016 09:26
Hm I was fiddling with the type enforcement thing but I think that was a separate issue. Thank you though I will double check
Yeah same error (minus the warning)
Luca Guidi
@jodosha
Jun 20 2016 09:27
@backus I've got the same problem: dry-rb/dry-validation#183
John Backus
@backus
Jun 20 2016 09:27
Ah
Well cool :)
Less work for me
Luca Guidi
@jodosha
Jun 20 2016 09:28

@backus The only way to make it to work is:

configure do
  predicates MyPredicates
end

Please check if this works for you.

Piotr Solnica
@solnic
Jun 20 2016 09:29
@AMHOL how can we deprecate config.predicates =???
I need to override it + add a warning
John Backus
@backus
Jun 20 2016 09:30
@jodosha that worked! Thank you
Luca Guidi
@jodosha
Jun 20 2016 09:30
;)
Andy Holland
@AMHOL
Jun 20 2016 09:31
Hmm, not sure, it's used internally still
John Backus
@backus
Jun 20 2016 09:31
Are all config.setting = things deprecated?
Andy Holland
@AMHOL
Jun 20 2016 09:31
Perhaps dry-configurable needs private settings or something
John Backus
@backus
Jun 20 2016 09:31
or just the predicates?
Piotr Solnica
@solnic
Jun 20 2016 09:32
just predicates
John Backus
@backus
Jun 20 2016 09:32
kk
Andy Holland
@AMHOL
Jun 20 2016 09:32
Actually, that feels weird
Perhaps just move it out of config?
To an ivar on the schema
Piotr Solnica
@solnic
Jun 20 2016 09:33
I just wanted to keep backward compat
it was moved already
Andy Holland
@AMHOL
Jun 20 2016 09:35
How about sth like:
      setting :predicates, nil

      def self.predicates(predicate_set = nil)
        warn 'config.predicates is deprecated and will be removed in version x' if config.predicates
        if predicate_set
          @predicates = predicate_set
          set_registry!
        else
          @predicates || Types::Predicates
        end
      end
John Backus
@backus
Jun 20 2016 09:37
Oh weird so the configure block also needs to come before the schema definition now
confused me for a bit longer
John Backus
@backus
Jun 20 2016 09:43
Alright I've got one more little conundrum for you guys
Although statistically I'm sure @jodosha has already opened an issue for it
Fran Worley
@fran-worley
Jun 20 2016 09:44
:laughing:
John Backus
@backus
Jun 20 2016 09:44
$ cat test.rb
require 'dry/validation'

schema =
  Dry::Validation.Schema do
    configure { config.type_specs = true }

    hash? do
      required('data', :hash).schema do
        required('attributes', :hash).schema do
          required('age', :int).value(:even?)
        end
      end
    end
  end

p schema.call('data' => { 'attributes' => {} })
p schema.call('data' => {})

$ be ruby test.rb
#<Dry::Validation::Result output={"data"=>{"attributes"=>{}}} messages={"data"=>{"attributes"=>{"age"=>["is missing"]}}}>
#<Dry::Validation::Result output={"data"=>{}} messages={"attributes"=>["is missing"]}>
For the second output: I expected it to be {"data"=>{"attributes"=>["is missing"]}}
But for some reason "data" is dropped
Not true for the first example
Piotr Solnica
@solnic
Jun 20 2016 09:47
@backus configure { config.type_specs = true }
John Backus
@backus
Jun 20 2016 09:47
Thanks
Nesting of messages is still an issue with that applied
but I'll update that little snippet
Andy Holland
@AMHOL
Jun 20 2016 09:48
Take it that's to do with dropping the first key to stop the nil => {...} errors hash?
John Backus
@backus
Jun 20 2016 09:49
Ah that sounds like a potential culprit
This was an issue before upgrading to most recent master
Let me check my old revision to see if that was before that change
Piotr Solnica
@solnic
Jun 20 2016 09:50
oh and you want value(:int?, :even?) we don’t infer predicates from type specs (yet)
John Backus
@backus
Jun 20 2016 09:50
Ah
No
I just need the messages nested properly
#<Dry::Validation::Result output={"data"=>{}} messages={"attributes"=>["is missing"]}>
should be
#<Dry::Validation::Result output={"data"=>{}} messages={"data"=>{"attributes"=>["is missing"]}}>
So we were previously using dry-rb/dry-validation@fa55777 (diff with current master: https://github.com/dry-rb/dry-validation/compare/fa557778ff0fbf8286eabeb17d72185284306328...master) so it looks like that predated the bugfix you are referring to @AMHOL
Piotr Solnica
@solnic
Jun 20 2016 09:53
it works when you drop hash? do .. end :/
John Backus
@backus
Jun 20 2016 09:55
:(
That would be less safe though assuming I want to enforce that the input value is a hash, right?
Piotr Solnica
@solnic
Jun 20 2016 09:58
yeah, I think we should make it nicer from the dsl pov though (and get rid of that issue at the same time) by having a dedicated way of specifying what the input should be
ie input :hash or something
it would simply prepend a rule
John Backus
@backus
Jun 20 2016 09:59
Interesting
Piotr Solnica
@solnic
Jun 20 2016 10:00
and it would be less nesting
so ie:
Dry::Validation.Schema do
  input :hash

  required(:foo, :int).maybe(:int?, :even?)
end

# or this for array input that would automatically use `each` rule

Dry::Validation.Schema do
  input :array

  required(:foo, :int).maybe(:int?, :even?)
end
defo nicer than each { schema { required(:foo, :int).maybe(:int?, :even?) } }
Andy Holland
@AMHOL
Jun 20 2016 10:02
:+1:
John Backus
@backus
Jun 20 2016 10:02
Yeah
I think the messages format might also benefit from a small redesign maybe?
Piotr Solnica
@solnic
Jun 20 2016 10:02
what’s your suggestion?
John Backus
@backus
Jun 20 2016 10:03
Right now it is still unclear how the messages refer to the input itself when they currently try to speak in terms of keys
So we do a bit of additional validation on top of what dry-validation checks and we essentially construct a simple JSON pointer (https://tools.ietf.org/html/rfc6901)
Nice thing is that you can still talk about arbitrary members of an object (#/foo/0 is the first entry in the array under the key foo)
but also it has a representation for the root element
Piotr Solnica
@solnic
Jun 20 2016 10:06
that’s interesting
I’ll be focusing on error messages (again) in 0.9.0
John Backus
@backus
Jun 20 2016 10:06
:)
Piotr Solnica
@solnic
Jun 20 2016 10:06
it’s currently a performance bottleneck
John Backus
@backus
Jun 20 2016 10:06
We'll be sure to upgrade quickly and help fuzz :P
I'm off for now. Night
Piotr Solnica
@solnic
Jun 20 2016 10:07
:wave:
John Backus
@backus
Jun 20 2016 10:09
(I'll make a note to open an issue for this tomorrow when I'm in the office)
Piotr Solnica
@solnic
Jun 20 2016 10:10
@backus thanks :)
dry-rb/dry-validation#193 #help-wanted
Piotr Solnica
@solnic
Jun 20 2016 11:29
dry-rb/dry-validation@0da593f <= dis :sparkles:
Nikita Shilnikov
@flash-gordon
Jun 20 2016 11:57
that's how functional approach works: you add two lines and get 13% performance boost :)
Piotr Solnica
@solnic
Jun 20 2016 12:04
yeah I’m pretty sure we can boost perf by ~30-40% for 1.0.0
atm dry-v is ~2.2x faster against an AM::Validation model without coercions, which is already a great result
but we can do better :)
although I gotta measure how well the perf scales, so ie what happens when the schema grows
John Backus
@backus
Jun 20 2016 19:18
K issue opened as promised dry-rb/dry-validation#194
Piotr Solnica
@solnic
Jun 20 2016 19:19
folks, if you’re using dry-types and would like to have default values being set automatically when no attributes are passed down to Struct.new with constructor set to :schema, please help wrapping this up…more info here: https://github.com/dry-rb/dry-types/issues/97#issuecomment-226288047 /cc @backus
John Backus
@backus
Jun 20 2016 19:24
Cool
So is the expected behavior here that, if I have one attribute with a default and two without, then the default attribute will be filled in if I construct the object with only the two attributes without defaults?
For example, from @dgollahon's issue:
class Foo < Dry::Types::Struct
  attribute :a, Dry::Types['strict.int']
  attribute :b, Dry::Types['strict.int'].default(17)
  attribute :c, Dry::Types['strict.int']
end

Foo.new(a: 1, c: 2).b # => 17
Or are you saying that, in that case, if I call Foo.new then the defaults are filled in and if I call Foo.new(a: 1, c: 2) then it errors? Because that is not useful to us
Piotr Solnica
@solnic
Jun 20 2016 19:29
defaults are already filled in for empty hash, but if you provide partial attributes then it won’t work atm, that’s the missing bit
I want this to only work for constructor_type(:schema) because in :strictmode I don’t want defaults to be used at all
John Backus
@backus
Jun 20 2016 19:29
I see
Yeah we just want different things
To clarify, my understanding is that you want the :strict type to not fill in defaults and not permit unexpected keys. You also want :schema to ignore unexpected keys and fill in defaults. Is that correct?
Piotr Solnica
@solnic
Jun 20 2016 19:34
yep
John Backus
@backus
Jun 20 2016 19:36
Yeah so maybe we use Dry::Types::Structs differently. We want something strict that can fill in defaults while also flagging unexpected keys
Maybe our use cases are different? Let me give you an example of why we want this
Piotr Solnica
@solnic
Jun 20 2016 19:40
this type of strictness (raising on unexpected keys) doesn’t work well with rom-rb where you may have join-keys that you don’t want to have in your structs so that’s why it works the way it works
John Backus
@backus
Jun 20 2016 19:40

We are using dry-types and dry-validation for our API. We might have a dry-v
schema that looks like this:

Dry::Validation.Schema do
  hash? do
    required('name', :hash).schema do
      required('first', :str).value(:filled?, max_size?: 100)
      required('last', :str).value(:filled?, max_size?: 100)
    end

    optional('similarity_threshold', :float).value(min?: 0.0, max?: 1.0)
  end
end

meaning we want to accept either

{
  "name": {
    "first": "John",
    "last":  "Backus"
  },
  "similarity_threshold": 1.0
}

or

{
  "name": {
    "first": "John",
    "last":  "Backus"
  }
}

but not

{
  "name": {
    "first": "John",
    "last":  "Backus"
  },
  "similarity_threshold": null
}

Then when this JSON is coerced and validated we want to invoke an object like this:

class SearchInput < Dry::Types::Struct
  attribute :name, Types::Name,
  attribute :similarity_threshold, Dry::Types['strict.float'].default(1.0)
end
Yeah I get the rom-rb perspective I just want to know if this sort of behavior fits into the framework of an option you think dry-types should provide
Piotr Solnica
@solnic
Jun 20 2016 19:42
so it doesn’t look like you need to raise on unexpected keys as schema will provide a valid attrs hash already, no?
John Backus
@backus
Jun 20 2016 19:43
Yeah sort of but we are trying to use dry-validations and dry-types here for slightly different reasons
dry-validation is our validation layer which builds user facing error messages
then additionally, at certain boundaries of our application, we use dry-types objects to enforce certain contracts
So we want the dry-types as a sort of sanity check
Kind of like how you might add both validations and database constraints
Piotr Solnica
@solnic
Jun 20 2016 19:45
I see, and you want defaults to kick in too in structs?
so you want 1) defaults 2) raising on unexpected keys 3) raising on missing keys (?)
John Backus
@backus
Jun 20 2016 19:45
Yeah
Piotr Solnica
@solnic
Jun 20 2016 19:45
and you want to raise on missing keys only if type has no default?
John Backus
@backus
Jun 20 2016 19:46
Yeah
Piotr Solnica
@solnic
Jun 20 2016 19:46
ok so :schema constructor won’t cut it
John Backus
@backus
Jun 20 2016 19:46
Yup we have just been using it as a workaround so far
Part of why we wanted to add dry-rb/dry-types#70
Piotr Solnica
@solnic
Jun 20 2016 19:47
so we just need to add another constructor type + tweak .new for it
John Backus
@backus
Jun 20 2016 19:47
Ah see that PR then
Happy to rebase it if you want
Piotr Solnica
@solnic
Jun 20 2016 19:48
yeah we should add it if you need it
I’m not super happy with the naming though ie :strict is not very self-explanatory :)
John Backus
@backus
Jun 20 2016 19:49
Yeah
Piotr Solnica
@solnic
Jun 20 2016 19:49
I’m not “attached” to this name in any way, really
so if you have any suggestions, I’m really open to that
John Backus
@backus
Jun 20 2016 19:50
Yeah I'm brainstorming now
:strictish
(joking)
Piotr Solnica
@solnic
Jun 20 2016 19:50
:laughing:
:sort_of_strict ;)
John Backus
@backus
Jun 20 2016 19:52
Only thing that comes to mind so far is :permissive but doesn't feel great
Piotr Solnica
@solnic
Jun 20 2016 19:54
I’d be ok with renaming current struct to permissive and adding new strict which does what you need
I’m only a lil bit uncertain about setting defaults in strict mode by…default :)
John Backus
@backus
Jun 20 2016 19:55
Yeah
Could name it optional
just throwing out things that come to mind
injectable
Daniel Gollahon
@dgollahon
Jun 20 2016 19:57
it seems like some of these would be better resolved by passing an option to the constructor type or just having a different part of the dsl
so you could say something like allow_defaults: true, reject_extraneous_keys: true, raise_on_missing_keys: true
perhaps as arguments inside constructor_type or elsewhere
Piotr Solnica
@solnic
Jun 20 2016 19:58
we could try that but I’m really careful with option-based APIs as they alter run-time behavior and on a larger scale it becomes a mess
Daniel Gollahon
@dgollahon
Jun 20 2016 19:59
yeah, it could be tricky. but i don't know that the constructor_type(...) pattern scales especially well either
Piotr Solnica
@solnic
Jun 20 2016 19:59
assuming we can capture all valid use cases and encapsulate them in dedicated objects - yes it should scale well
with options you create lots of different behavior combinations :/
Daniel Gollahon
@dgollahon
Jun 20 2016 20:00
that's true
Piotr Solnica
@solnic
Jun 20 2016 20:00
that’s what killed virtus (IMO)
remember that every option ends up as an if added in some run-time code :)
Daniel Gollahon
@dgollahon
Jun 20 2016 20:01
but right now there are missing, but valid use cases (like @backus mentioned). it's also a bit confusing as to which one does what when there's really no good name for the different combinations.
Piotr Solnica
@solnic
Jun 20 2016 20:01
yeah I agree with that
Daniel Gollahon
@dgollahon
Jun 20 2016 20:01
yeah, i'm not saying that it's absolutely the greatest fix, just thinking aloud.
Piotr Solnica
@solnic
Jun 20 2016 20:02
it just needs some experimentation until we find what works best for us all :)
John Backus
@backus
Jun 20 2016 20:02
@solnic could you reopen dry-rb/dry-types#70 btw?
I don't have permission
Thanks
Piotr Solnica
@solnic
Jun 20 2016 20:03
you don’t? huh I added you as a collaborator long time ago
John Backus
@backus
Jun 20 2016 20:03
Maybe I'm dumb and didn't see it
I have commit access so not sure
John Backus
@backus
Jun 20 2016 20:33
Alright well dry-rb/dry-types#70 is rebased
I'm not sure if we agreed on a course of action for this rename. Maybe it should just stay as :strict_with_defaults?
My takeaway is that, if a option-based API isn't doable (I understand the pain that introduces to a maintainer), then it would be nice if there was a concrete lower level API that I could drop down to for our structs
which would let me introspect on the struct's definition
and ask something like "which attributes have defaults and what are they?"
Right now the awkwardness is floating around the fact that I don't know if I am able to do that without using private API that might be broken in any commit
combined with the fact that the struct checking stuff is defined in .new which I think makes it more awkward than if I could just do like
def initialize(options)
  super(self.class.attributes.defaults_hash.merge(options))
end
John Backus
@backus
Jun 20 2016 20:39
This feels like a classic example of
Finding a high-level abstraction (a DSL or a single-method interface, doesn’t matter) is much simpler than figuring out lower-level abstractions afterwards.
Piotr Solnica
@solnic
Jun 20 2016 21:00
@backus hah this quote looks familiar ;)
we can move things to the initialize method
John Backus
@backus
Jun 20 2016 21:00
Cool
Piotr Solnica
@solnic
Jun 20 2016 21:00
and I'm OK with :strict_with_defaults but we still need to decide on raising on unexpected keys
if we add that only to :strict_with_defaults then NOT having it in :strict would be confusing for the users
John Backus
@backus
Jun 20 2016 21:02
Yeah true
Also OT but what does adding config.type_specs = true do?
Is the difference that, without this flag, required(:foo, :str).value(:filled?) wouldn't actually check that foo is a string?
Piotr Solnica
@solnic
Jun 20 2016 21:03
it will build input processor from explicit type specs
John Backus
@backus
Jun 20 2016 21:03
Ah
Piotr Solnica
@solnic
Jun 20 2016 21:04
we do not infer predicates from type specs yet, it's up for discussion
it's more complex than it may seem to be
John Backus
@backus
Jun 20 2016 21:04
Ok I think I know what this means but let me make sure
So when you say it builds an input processor from explicit type specs
you mean that, in the case of the example above, dry-validation then uses some string specific processor to evaluate the value?
Ah ok so reading the specs
it looks like it changes coercion behavior?
Piotr Solnica
@solnic
Jun 20 2016 21:10
it doesn't change coercion behavior, it uses same dry-types as in 0.7.0
it's just a way of separating coercion from validation with a thick line
John Backus
@backus
Jun 20 2016 21:10
Ah ok
Piotr Solnica
@solnic
Jun 20 2016 21:11
we still have to figure out a good way of defining schemas, I'm still on the fence with having everything in a single schema
ie I think I'd prefer to keep http-specific schema with basic coercion and type-checking separately from a "domain validation" schema
John Backus
@backus
Jun 20 2016 21:13
I'm not totally sure what you mean by a single schema here
I think what you're saying is that, if I do Dry::Validation.JSON then there should be one isolated step that does coercions from the JSON domain to the standard domain
and then validations should only be described in terms of the standard domain
Is that accurate?
Piotr Solnica
@solnic
Jun 20 2016 21:15
yeah that's how it works already but it's part of a single process handled by a single schema
steps are separated internally but you define everything in a single schema (from dsl pov)
so ie required(:age, :int).maybe(:int?, gt?: 18) combines basic type checking with domain rules
and :int is used for coercion in Form
John Backus
@backus
Jun 20 2016 21:16
Ahh ok I follow now
So you're saying that ideally maybe you define two explicit steps in some dry-v DSL
a process input step and a validate step
Piotr Solnica
@solnic
Jun 20 2016 21:18
either this or just have 2 schemas, where the domain one could use info from the base one to avoid some level of duplication
John Backus
@backus
Jun 20 2016 21:19
Seems like a nice thing to define side by side
Conversation for another day probably
Piotr Solnica
@solnic
Jun 20 2016 21:19
yeah we're talking about 1.0.0 stuff :)
gonna take a while
John Backus
@backus
Jun 20 2016 21:20
I look forward to that day
Do you still contract? Might be interesting at some point to just have you review some of our dry-* usage
Piotr Solnica
@solnic
Jun 20 2016 21:20
it'd be good if the type-safety aspect of dry-v was really clearly visible somehow
not anymore, I went full-time with MojoTech 2 months ago
John Backus
@backus
Jun 20 2016 21:21
Yeah I heard you mention that
wasn't sure if mojotech was similar to like thoughtbot or something
where the difference is we just coordinate an engagement with you via mojotech
Piotr Solnica
@solnic
Jun 20 2016 21:23
that might work, I'd have to ask at mojo
John Backus
@backus
Jun 20 2016 21:23
anyways
if we add that only to :strict_with_defaults then NOT having it in :strict would be confusing for the users
Is updating the behavior for :strict in the cards?
Piotr Solnica
@solnic
Jun 20 2016 21:24
yes, but we need current strict behavior, it would have to be moved to a different schema type and used as default
John Backus
@backus
Jun 20 2016 21:25
Alright let me draft a quick proposal then for the new constructor types
I'll try to be quick since I know its late for you
Piotr Solnica
@solnic
Jun 20 2016 21:26
:ok:
John Backus
@backus
Jun 20 2016 21:31
found a bug in the process I think
class StrictUser < Dry::Types::Struct
  constructor_type(:strict)

  attribute :name, 'strict.string'
  attribute :gender, Dry::Types['strict.string'].default('male')
end
StrictUser.new # => #<NoMethodError: undefined method `default?' for "strict.string":String>
LMK if I should open an issue
Piotr Solnica
@solnic
Jun 20 2016 21:36
yes this should be resolved to a type, not sure why it was passed down as a string
as in, looks like a bug
John Backus
@backus
Jun 20 2016 21:37
kk will open an issue after all of this
Hopefully gitter supports tables
constructor_type Extra keys Defaults when given no params Defaults when given some params
:strict Yes Yes No
:schema Yes Yes Yes
Great
That is the current behavior and I intentionally left out :symbolized because it isn't relevant
When you have a moment give me a :thumbsup: or something to confirm the table above while I construct the proposal table
John Backus
@backus
Jun 20 2016 21:42
@solnic proposal:
constructor_type previous constructor_type Extra keys Defaults when given no params Defaults when given some params
:strict N/A No No No
:strict_with_defaults N/A No Yes Yes
:permissive :strict Yes Yes No
:schema :schema Yes Yes Yes
John Backus
@backus
Jun 20 2016 21:48
I'll work on a PR if you agree
John Backus
@backus
Jun 20 2016 21:54
Maybe both default columns for :permissive should be No?
John Backus
@backus
Jun 20 2016 22:47
Sorry if I'm missing something but I'm unclear on what doing configure { config.type_specs = true } buys me as an end user
Specifically, I am trying to update my dry-validation configuration test and I'm not sure how to assert the behavior
I know that I could do like expect(schema.type_map).to_not be_empty
but I don't use that
So I'm not clear on why I should add this configuration right now
Piotr Solnica
@solnic
Jun 20 2016 22:50
this is for the transition period prior 1.0
you need to enable this option if you want to specify types explicitly and have coercion inferred from these definitions
John Backus
@backus
Jun 20 2016 22:50
Ah alright so I should basically assert the coercion behavior
Thanks
Piotr Solnica
@solnic
Jun 20 2016 22:51
in 1.0 w/o type specs coercion won't be configured
John Backus
@backus
Jun 20 2016 22:51
Do you have a target date for 1.0?
Piotr Solnica
@solnic
Jun 20 2016 22:52
omg no :)
John Backus
@backus
Jun 20 2016 22:52
Haha ok
Piotr Solnica
@solnic
Jun 20 2016 22:52
I'm done with dates
John Backus
@backus
Jun 20 2016 22:52
You've mentioned it a lot
so I was wondering if that was exerting pressure on these decisions
Piotr Solnica
@solnic
Jun 20 2016 22:52
rom 2.0 eta was the last time I did that
John Backus
@backus
Jun 20 2016 22:52
:P
Piotr Solnica
@solnic
Jun 20 2016 22:53
my new eta from now on will be "it's done when it's done" #realitycheck
John Backus
@backus
Jun 20 2016 22:54
Heh
Also sorry for prodding but any thoughts on the table I shared above?
Piotr Solnica
@solnic
Jun 20 2016 22:55
yeah thanks for that, I'll check it out in the morning, 1am here and my sight and thinking is blurred :)
John Backus
@backus
Jun 20 2016 22:55
Haha alright
Sleep well
Piotr Solnica
@solnic
Jun 20 2016 22:56
:) :zzz:
John Backus
@backus
Jun 20 2016 22:57
Actually I have one more question lol
$ ag "(?:optional|required)\([:'\"]\w+['\"]?, :\w+\)"
spec/integration/schema/array_schema_spec.rb
35:            required(:prefix, :int).filled
36:            required(:value, :int).filled

spec/integration/schema/form/explicit_types_spec.rb
6:        required(:age, :int)
19:        required(:age, :int).value(:int?, gt?: 18)
78:          required(:email, :string)
79:          required(:age, :int)
82:            required(:street, :string)
83:            required(:city, :string)
84:            required(:zipcode, :string)
87:              required(:lat, :float)
88:              required(:lng, :float)
130:          required(:title, :string)
134:              required(:name, :string)

spec/integration/schema/hash_schema_spec.rb
29:          required(:prefix, :int).filled
30:          required(:value, :int).filled

spec/integration/schema/json/explicit_types_spec.rb
6:        required(:bdate, :date)
19:        required(:bdate, :date).value(:date?, gt?: Date.new(2009))
78:          required(:email, :string)
79:          required(:bdate, :date)
82:            required(:street, :string)
83:            required(:city, :string)
84:            required(:zipcode, :string)
87:              required(:lat, :float)
88:              required(:lng, :float)
130:          required(:title, :string)
134:              required(:name, :string)

spec/integration/schema_spec.rb
10:        required(:email, :string).filled
So these are all the types I see in the specs
:int, :string, :float, :date
Say I needed something like :time
How do I figure out if that is a valid type symbol without asking you?
Piotr Solnica
@solnic
Jun 20 2016 22:59
all dry-types identifiers are supported
so if dry-types has it, it will work
John Backus
@backus
Jun 20 2016 22:59
Ah so anything that goes into Dry::Types[] works
got it
Piotr Solnica
@solnic
Jun 20 2016 22:59
yep
John Backus
@backus
Jun 20 2016 22:59
That is neat
Piotr Solnica
@solnic
Jun 20 2016 23:00
and Form and JSON uses form and json categories, respectively
and you can pass in your own dry-type object too
required(:foo, MyFoo) works too
John Backus
@backus
Jun 20 2016 23:00
Thats great
Given that we are already duplicating our dry-validation and dry-type definitions
this should be a huge help
Piotr Solnica
@solnic
Jun 20 2016 23:01
yeah that's why it's there
if you have types in multiple places, just re-use them
John Backus
@backus
Jun 20 2016 23:01
:)