These are chat archives for dry-rb/chat

16th
Jun 2016
Piotr Solnica
@solnic
Jun 16 2016 10:43
folks, I need feedback re https://github.com/dry-rb/dry-validation/issues/181#issuecomment-226450344 /cc @jodosha @AMHOL @fran-worley @timriley
Piotr Solnica
@solnic
Jun 16 2016 11:01
this really boils down to explicit vs implicit, initially I thought having coercion is so common that making it auto-magically work would be a win, but as always, implicit behavior + magic == trouble, so there you have it :D
not to mention that with this explicit API we can really easily support custom coercion objects that respond to #[]
oh and defining a huge schema (guys from shopify gave me an example) takes FIVE SECONDS because of coercion inference
so this must be absolutely improved in 0.8.0
Jake Sower
@jakesower
Jun 16 2016 12:38
hi, I'm a new dry-validation user. I'm trying to get a field to validate against some schema, Resource or an array of Resources. my gut tells me that optional(:data){ schema(Resource) | (array?.then(each(schema(Resource)))) } should be the correct way of expressing this, but it looks like it doesn't like seeing schema within the block, but rather in the form optional(:data).schema(Resource). how should I go about making this work? I need it to support Resources or arrays of Resources. thanks in advance!
Piotr Solnica
@solnic
Jun 16 2016 12:52
@jakesower each doesn’t support this syntax yet, I’ll try to add it in 0.8.0
try optional(:data).each { schema(Resource) } not sure if that works tbh but pls try
Jake Sower
@jakesower
Jun 16 2016 12:54
thanks Piotr. that works fine when I give it an array of Resources (e.g. [{id: '5', type: 'dataset'}], but not with a single resource, e.g. {id: '5', type: 'dataset'} (it fails with message {:data=>["must be an array"]})
I'm happy to hack around it with something on the ugly side, if that'll work as a stopgap.
Piotr Solnica
@solnic
Jun 16 2016 12:56
@jakesower try this optional(:data) { array? & each { schema(Resource) } | schema(Resource) }
or maybe a high-lvl rule:
Jake Sower
@jakesower
Jun 16 2016 12:57
first one doesn't compile: ArgumentError: +each+ is not a valid predicate name
Piotr Solnica
@solnic
Jun 16 2016 12:58
optional(:data) { array? | hash? }

rule(valid_data: [:data]) do |data|
  data.array?.then(data.each(Resource) | data.hash?.then(schema(Resource))
end
Jake Sower
@jakesower
Jun 16 2016 13:01

That doesn't compile either. (Simplified version)

require 'dry-validation'
X = Dry::Validation.Schema do
  optional(:data) { array? | hash? }
end

ArgumentError: wrong number of arguments (0 for 1..3)

Piotr Solnica
@solnic
Jun 16 2016 13:07
ah right sorry I’m on master ;)
Jake Sower
@jakesower
Jun 16 2016 13:07
easy enough for me to switch over. I've seen there's some debate about the final format of things, but if it'll be there in 0.8, that's fine.
Piotr Solnica
@solnic
Jun 16 2016 13:12
I’ll try to improve each + schema for 0.8.0 or 0.8.1
Jake Sower
@jakesower
Jun 16 2016 13:13
great. I need to familiarize myself with the source code anyway. thank you for your time and help.
Piotr Solnica
@solnic
Jun 16 2016 13:14
@jakesower I added an issue about this dry-rb/dry-validation#187
Jake Sower
@jakesower
Jun 16 2016 13:15
thank you.
Joe Van Dyk
@joevandyk
Jun 16 2016 18:09
if i have a dry-type struct.. what’s the best way to load json into it?

like this:

class Questions::Question < Dry::Types::Struct
  QuestionType = Types::Strict::String.enum('multiple_select', 'text')

  attribute(:id, Types::Strict::Int)
  attribute(:text, Types::Strict::String)
  attribute(:type, QuestionType)
  attribute(:options, Types::Strict::Array.member(Questions::Option))
end

and i have json that looks like that.. how can i create that kind of object?

Nikita Shilnikov
@flash-gordon
Jun 16 2016 18:14
I guess the right way is to create a dry-v schema and populate your struct with its output
Joe Van Dyk
@joevandyk
Jun 16 2016 18:17
can i automatically create a dry-v schema based off the type schema here?
Andrew Kozin
@nepalez
Jun 16 2016 18:18
@joevandyk you could create special coercible type 'coercible.questions.question' whose constructor parses json
Joe Van Dyk
@joevandyk
Jun 16 2016 18:18
not sure what that looks like
also is dry-types usable in rails dev mode yet?
Andrew Kozin
@nepalez
Jun 16 2016 18:20
I use it in commercial rails-based project (thanks to dry-types it is now not too railsy)
Joe Van Dyk
@joevandyk
Jun 16 2016 18:24
@nepalez isn’t there a gem that fixes the dev loading problem?
@nepalez i was sorta thinking i needed a hash schema or something
Andrew Kozin
@nepalez
Jun 16 2016 18:26

I would define coercible type in a way:

require 'json'

definition = Dry::Types::Definition.new(Questions::Question).constructor do |value|
  (String === value) ? JSON.parse(value) : value
end
Dry::Types.register 'coercible.questions.question', definition
define_constants Types, ['coercible.questions.question']

then use it

Types::Coercible::Questions::Question[some_json]
You could also reload its constructor (but it's a sort of hack IMO)
class Questions::Question < Dry::Types::Struct
  def self.new(data)
    super((String === data) ? JSON.parse(data) : data)
  end
end
Joe Van Dyk
@joevandyk
Jun 16 2016 18:30
hm, would a json schema be better?
Piotr Solnica
@solnic
Jun 16 2016 18:30
why not just define a schema for your json?
then you can just pass its output to your class constructor
joevandyk @joevandyk mumbles about not finding json in dry-v docs
Joe Van Dyk
@joevandyk
Jun 16 2016 18:30
;)
Piotr Solnica
@solnic
Jun 16 2016 18:30
we have partial support for infering schemas from structs but that’s quite experimental still
Joe Van Dyk
@joevandyk
Jun 16 2016 18:31
@solnic can i pass nested hash input to class constructor?
Andrew Kozin
@nepalez
Jun 16 2016 18:31
@solnic hi! could you take a look at dry-types#98 ?
Piotr Solnica
@solnic
Jun 16 2016 18:31
@nepalez will do but tomorrow :)
Andrew Kozin
@nepalez
Jun 16 2016 18:31
thank you!
Joe Van Dyk
@joevandyk
Jun 16 2016 18:31
i.e Question.new(choices: [{id: …}])
Andrew Kozin
@nepalez
Jun 16 2016 18:35
@joevandyk I hate rails autoloading, and load types manually
Or, more accurately, I load structs in app/values (autoloading, yes) and define additional types in a lib by hand
Piotr Solnica
@solnic
Jun 16 2016 18:36
IIRC the issue is that structs/values register themselves in the types container automatically
so when rails removes the constant, it gets loaded again, and registered again, and then some code can have references to the old constant #yaycodereloading
Joe Van Dyk
@joevandyk
Jun 16 2016 18:40
@solnic i was running into problems of passing nested hash input to a dry struct, like Question.new(choices: [{id: …}]) — what’s a good way around that?
it was complaining that choices wasn’t valid input, I had to do something like Question.new(choices: [Choice.new(id: …)])
Piotr Solnica
@solnic
Jun 16 2016 18:42
@joevandyk that’s…impossibru, this shuold work with hashes+arrays
I use dry-types with rom-rb where this happens all-the-time
ie every time you load an aggregate a nested hash with arrays-of-hashes is passed in
report an issue if you can reproduce this
Joe Van Dyk
@joevandyk
Jun 16 2016 18:45
hm.. i can’t reproduce anymore.. probably my fault
Piotr Solnica
@solnic
Jun 16 2016 18:45
cool
Joe Van Dyk
@joevandyk
Jun 16 2016 18:52
if i have an enum, how can i use that in a json schema?
Piotr Solnica
@solnic
Jun 16 2016 18:53
@joevandyk iirc key(:foo).required(YourEnum)
Joe Van Dyk
@joevandyk
Jun 16 2016 18:53
hm.. didn’t seem to work.. trying agian
Piotr Solnica
@solnic
Jun 16 2016 18:54
key(:foo).required(type?: YourEnum) O_o
Andrew Kozin
@nepalez
Jun 16 2016 18:54
maybe required(included_in: [...]) ?
Piotr Solnica
@solnic
Jun 16 2016 18:57
no this should work with enums and extract its rule
Andrew Kozin
@nepalez
Jun 16 2016 18:58
i see. one more thing required(type: ...) (without ? in this syntax, iirc)
Joe Van Dyk
@joevandyk
Jun 16 2016 18:58
i get type is not a valid predicate name
Piotr Solnica
@solnic
Jun 16 2016 18:58
yeah so required(YourType) should work, if it doesn’t, pls report an issue
Joe Van Dyk
@joevandyk
Jun 16 2016 18:59
NoMethodError: undefined method `visit_[:type, "string"]' for #<Dry::Types::Compiler:0x007f4e49ac4a88 @registry=Dry::Types>
Piotr Solnica
@solnic
Jun 16 2016 19:00
@joevandyk works on master ;)
Joe Van Dyk
@joevandyk
Jun 16 2016 19:00
doh
i’ll try it
Piotr Solnica
@solnic
Jun 16 2016 19:01
oh I wouldn’t recommend that
unless you want to switch to the bleeding edge
it needs types and logic from master too
we’re been doing lots of improvements/fixes
Joe Van Dyk
@joevandyk
Jun 16 2016 19:01
bleeding edge fine with me as long as stuff seems to work while testing
yes, it worked! thanks
hopefully last question.. in a dry-v json schema, how can i indicate that a key’s value is a hash, but the hash can be whatever contents
:hash? looks like
Joe Van Dyk
@joevandyk
Jun 16 2016 19:09
i was expecting that required(:foo).filled(:string?) would work.. telling me string no good
Andrew Kozin
@nepalez
Jun 16 2016 19:10
you could check a type Types::Strict::String or Types::Hash
Joe Van Dyk
@joevandyk
Jun 16 2016 19:10
yeah
what’s the syntax in dry-v for defining a key’s value is an array of something?
ahh.. each
Joe Van Dyk
@joevandyk
Jun 16 2016 19:17
@nepalez do you know of any reason :string? doesn’t work, but :int? and :hash? does?
Jake Sower
@jakesower
Jun 16 2016 19:21
@joevandyk have you tried :str?
Joe Van Dyk
@joevandyk
Jun 16 2016 19:21
nope.. trying
yeah, that’s it
Andrew Kozin
@nepalez
Jun 16 2016 19:23
seems like we need better docs for dry-logic ;)
Joe Van Dyk
@joevandyk
Jun 16 2016 19:27
oh i’ve given up on reading docs.. and just look for integration tests :)
Joe Van Dyk
@joevandyk
Jun 16 2016 19:38
if i have a json schema attribute like required(:id).filled(:int?) and id should be an int, and someone gives me input where id is a string, is there a way to automatically try to coerce id to a int?
maybe that happens in form schemas, not json?
what’s the difference between form and json schemas?
Jake Sower
@jakesower
Jun 16 2016 19:43
the form schemas deal with uncoerced input. I think that's what you want.
<--- total dry-validation newbie
Joe Van Dyk
@joevandyk
Jun 16 2016 19:44
ah ok
Joe Van Dyk
@joevandyk
Jun 16 2016 22:13
i have a json schema of an object. When someone makes a new object, it won’t have an ID column yet. How is that usually handled? Through a new schema?
i.e. if a User json object is like {“id”:123, “email_address”: ‘joe@tanga.com’} would i have an ‘new user’ json schema?
Joe Van Dyk
@joevandyk
Jun 16 2016 22:19
or just make the ID column optional?
Nikita Shilnikov
@flash-gordon
Jun 16 2016 22:26
the question is do you really need a struct object before ID assignment?
Joe Van Dyk
@joevandyk
Jun 16 2016 22:45
@flash-gordon this is a schema
Piotr Solnica
@solnic
Jun 16 2016 22:45
Json schemas don't enforce int coercion
Joe Van Dyk
@joevandyk
Jun 16 2016 22:46
when someone posts a new user, they will give me { email_address: ‘joe@tanga.com } — id would be missing — is it recommended to make the id key optional?
Piotr Solnica
@solnic
Jun 16 2016 22:46
Yeah if you want to use the same schema for both cases
I did that a couple of times for user form schema with or without password
Nikita Shilnikov
@flash-gordon
Jun 16 2016 22:57
@joevandyk my bad :) Besides optional keys a schema can be inherited from other schema https://github.com/dry-rb/dry-validation/blob/master/spec/integration/schema/inheriting_schema_spec.rb
Joe Van Dyk
@joevandyk
Jun 16 2016 23:03
i’m running into difficulties making a schema that looks like [{option_id: 1}, {option_id: 2}]
i’ve tried each { schema { required(:option_id).filled(:int?) } } but no luck
Joe Van Dyk
@joevandyk
Jun 16 2016 23:09
hm, it works with Dry::Validation.Schema, not with Dry::Validation.Form or JSON
Joe Van Dyk
@joevandyk
Jun 16 2016 23:17
dry-rb/dry-validation#188
Piotr Solnica
@solnic
Jun 16 2016 23:30
Yeah that is not supported yet
Joe Van Dyk
@joevandyk
Jun 16 2016 23:41
how can i make a schema that supports [{option_id: 1}] and [“some_string”]?
looking into rules but not sure of how to get the syntax right
Joe Van Dyk
@joevandyk
Jun 16 2016 23:55
can’t seem to find a test that would cover that functionality
Jake Sower
@jakesower
Jun 16 2016 23:57
@joevandyk I'm struggling with something similar-ish.
I think the right approach would be something like array?.then{ hash? | str? }
Joe Van Dyk
@joevandyk
Jun 16 2016 23:57
hm
Jake Sower
@jakesower
Jun 16 2016 23:58
one issue is that hash? doesn't compose well with others (this is a known issue)
I've been hacking around it with something like this:
predicate(:is_hash?) do |value|
    value.is_a?(Hash)
end
Joe Van Dyk
@joevandyk
Jun 16 2016 23:59
hm.. i have this right now:
Questions::Schemas::Answer = Dry::Validation.Schema do
  each do
    schema do
      required(:option_id).filled(:int?)
    end
  end
end