These are chat archives for dry-rb/chat

29th
Jul 2016
Piotr Solnica
@solnic
Jul 29 2016 00:00
But you do know the possible key names right?
Darcy Laycock
@Sutto
Jul 29 2016 00:00
nope! they can vary a lot and are added all the time.
Piotr Solnica
@solnic
Jul 29 2016 00:01
Oh damn. But if you trust the source then you could gen schemas dynamically (for now) based on input
So ie you could define rules and then generate a schema for the keys your system received
I will show you how but tomorrow. It's 2am over here and I'm on mobile :)
Darcy Laycock
@Sutto
Jul 29 2016 00:11
no problem - I'll have a play around :) Will see if I can the feature request reported and see if I can implement it also
one last question if you are still here - is there an implementation guide / anything other than the docs site + code to understand how it's implemented internally? If not, I'll dive in and have a play but figured I'd ask first
Piotr Solnica
@solnic
Jul 29 2016 00:28
@Sutto zero docs for internals, still changing so...it is based on dry-logic, the dsl in dry-v builds an ast representation of dry-logic rules, which gets compiled into a rule object graph which applies predicates to input
Darcy Laycock
@Sutto
Jul 29 2016 00:30
ok, cool :) I'll have a play around with it for the moment and see what I can get
Piotr Solnica
@solnic
Jul 29 2016 00:41
This is gonna be a crazy ride ;)
Philip Arndt
@parndt
Jul 29 2016 02:03
yay @Sutto
Darcy Laycock
@Sutto
Jul 29 2016 02:03
One other interesting question - is there an easy way to 'compose' schemas?
not via nesting, but for example this schema also includes another schema (ruby style mixins are what comes to mind, concept wise - but something explicit would be nice)
Darcy Laycock
@Sutto
Jul 29 2016 05:38
Questions for anyone who knows dry-validation pretty well: Are you able to explain how input processors and hash types work? Trying to understand what they mean exactly.
ah, I understand the hash type now
Darcy Laycock
@Sutto
Jul 29 2016 07:31
ah! so looking at dry-types more in depth makes a lot more sense now, understanding the json stuff well
Jean-Michel Garnier
@jmgarnier
Jul 29 2016 07:35
Thank you @solnic :+1:
Jean-Michel Garnier
@jmgarnier
Jul 29 2016 07:59
A question regarding dry-container. I am writing a gem which make it easy to connect to multiple DBs and I'd like to configure the list of dependencies inside a container in the gem source code. This gem will be used in a Rails app which does not use dry-container. I guess the easiest way is to introduce a Configuration class that will be called in a Rails initializer and instantiate the container. No need to expose the container to the Rails app (yet). Maybe I should ask this question in an gh issue of dry-container?
Alexey Kuznetsov
@semenovDL
Jul 29 2016 10:39

Hi. I need to validate list of field based on value of another field.
This code don't work correct in case, where :kind is nil.

FILLED_FIELDS_BY_KIND = {
  'a' => %i(x y z),
  'b' => %i(q w e)
}

required(:kind).value(included_in?: %w(a b))

%w(a b).each do |kind|
  optional(:kind).value(eql?: kind).when(:true?) do
    FILLED_FIELDS_BY_KIND[kind].each do |field|
      value(field).filled?
    end
  end
end

How I should write this validation rules?

Alexey Kuznetsov
@semenovDL
Jul 29 2016 10:51
I'm looking for something like this:
required(:kind).value(included_in?: %w(a b)).when(:true?) do |kind|
  FILLED_FIELDS_BY_KIND[kind].each do |field|
    value(field).filled?
  end
end
Piotr Solnica
@solnic
Jul 29 2016 11:01
@Sutto yes we can compose schemas with Dry::Validation.Schema(AnotherSchema) { .. }
henricus louwhoff
@hl
Jul 29 2016 14:53
This message was deleted
Kevin Ross
@rosskevin
Jul 29 2016 16:18
I have a problem that I can't sort out. I have a predicate id? that regardless what I return true || false it always states that it has failed validation.
        def id?(value)
          !value.nil? && value.kind_of?(Integer) && value > 0
        end
I have literally commented out the implementation and returned hardcoded true and false just to see if I could affect the result
calling with required(:sender_id).value(:id?) and I have debugged inside the predicate, all seems well
Piotr Solnica
@solnic
Jul 29 2016 16:27
@rosskevin can you show a full script repro?
Kevin Ross
@rosskevin
Jul 29 2016 16:29
unfortunately no, I think it is some kind of interplay with inheritance. I'll plug in unit tests for all my predicates as a starter just to get a sanity check then build up from there. in this situation I have an odd case of reform inheritance and standard inheritance. On that note:
My base schema class Schema < ::Reform::Form::Dry::Validations::DrySchema
which is the base schema that reform uses
but I create schema fragments with:
      def self.new_schema(base_schema = ::AfCore::Validations::Schema, &block)
        Dry::Validation.Schema(base_schema, &block)
      end
this Dry::Validation.Schema() has no bearing on inheritance correct?
in that it is not inheriting from self in any way
I just want to be sure my schema and fragments are ultimately extending ::Reform::Form::Dry::Validations::DrySchema so I don't have strange coercions
Piotr Solnica
@solnic
Jul 29 2016 16:34
inheritance in this case is extremely tricky, because of coercions vs validation rules, the system is already very flexible, but we might find some issues in places like Reform
Kevin Ross
@rosskevin
Jul 29 2016 16:35
I'm pretty sure I'll be the one to bump into the strangest of cases
Piotr Solnica
@solnic
Jul 29 2016 16:35
if you could repro this and report an issue we could look into that, @fran-worley is working on reform integration so we would figure this out together
this is good, please do and we will fix it :D
Kevin Ross
@rosskevin
Jul 29 2016 16:36
I will if I can narrow it down, as usual, the problem is usually with the user and not the library
Piotr Solnica
@solnic
Jul 29 2016 16:36
supporting edge cases is one of the reasons why this lib exists, really, so I don’t want to have cases where somebody wants to do something and we’re like “well, we don’t support this, it’s an edge case, not worth it”
Kevin Ross
@rosskevin
Jul 29 2016 16:36
that's good to know. hopefully I can extract it (which I think is doable)
in this specific case, I have a screwy hierarchy that is a mix of dry-v inheritance though and reform-dry-v inheritance, and it may make sense just to stick to only dry-v fragments and skip the reform-v inheritance. It's a crazy set of STI models + STI-based operations/validations - that's why it's hard to narrow down. Some hierarchical and some cross-cutting.
Piotr Solnica
@solnic
Jul 29 2016 16:39
yeah inheritance is always hard to deal with
Kevin Ross
@rosskevin
Jul 29 2016 16:41
so I've got a new symptom, indeed it seems like somehow I wired up base schema for some but not others. So likely user error. Thanks, I'll PR a unit test if I end up finding something worthwhile.
Kevin Ross
@rosskevin
Jul 29 2016 20:50
I have a screwy validation set, in one subclass, I have 0..n line items, in another subclass, I require 1..n line items. Is there a way to express this in the base class?
Required block is:
     required(:line_items).schema do
          required_id(:product_id)
          required(:quantity).value(:int?, gteq?: 0)
          optional(:period_start_at).maybe(:time?)
          optional(:period_end_at).maybe(:time?)
       end
Kevin Ross
@rosskevin
Jul 29 2016 21:06
This attempt failed miserably with +include+ is not a valid predicate name (ArgumentError)
module LineItemValidations
  def self.included(klass)
    klass.class_eval do
      required_id(:product_id)
      required(:quantity).value(:int?, gteq?: 0)
      optional(:period_start_at).maybe(:time?)
      optional(:period_end_at).maybe(:time?)
    end
  end
end

SCHEMA = Validations::Schema.new_schema(BaseDocument::SCHEMA) do
  required(:line_items).schema do
    include LineItemValidations
  end
end

SCHEMA_OPTIONAL_LINES = Validations::Schema.new_schema(BaseDocument::SCHEMA) do
  optional(:line_items).schema do
    include LineItemValidations
  end
end
Kevin Ross
@rosskevin
Jul 29 2016 21:21

I have followed the maybe nested hash DSL, and it seems to be evaluated without the context of my base schema, do I need to register it in the sub-schema?

        optional(:line_items).maybe do
          schema do
            required_id(:product_id)
            required(:quantity).value(:int?, gteq?: 0)
            optional(:period_start_at).maybe(:time?)
            optional(:period_end_at).maybe(:time?)
          end
        end

from http://dry-rb.org/gems/dry-validation/nested-data/

my custom base schema predicates aren't found inside the maybe do schema do blocks
Kevin Ross
@rosskevin
Jul 29 2016 21:27
Found it in the method signature, need to pass my base to the schema block
Piotr Solnica
@solnic
Jul 29 2016 21:28
@rosskevin you can just do required(:line_items).schema(LineItemSchema)
Kevin Ross
@rosskevin
Jul 29 2016 21:31
Ah, thanks. I can't seem to get the line_items to be optional {:line_items=>["must be a hash"]}
LINE_ITEMS = Validations::Schema.new_schema(Validations::Schema.new_schema) do
  required_id(:product_id)
  required(:quantity).value(:int?, gteq?: 0)
  optional(:period_start_at).maybe(:time?)
  optional(:period_end_at).maybe(:time?)
end

SCHEMA = Validations::Schema.new_schema(BaseDocument::SCHEMA) do
  required(:line_items).schema(LINE_ITEMS)
end

SCHEMA_OPTIONAL_LINE_ITEMS = Validations::Schema.new_schema(BaseDocument::SCHEMA) do
  optional(:line_items).maybe do
    schema(LINE_ITEMS)
  end
end
Piotr Solnica
@solnic
Jul 29 2016 21:33
@rosskevin required and optional are for keys, not values, so you need to do required(:line_items).maybe { schema(LineItemSchema) }
Kevin Ross
@rosskevin
Jul 29 2016 21:33
the line_items is a key
it's an optional sub-hash
Piotr Solnica
@solnic
Jul 29 2016 21:33
yes, and required means that the key must exist
optional means that a key could not exist
Kevin Ross
@rosskevin
Jul 29 2016 21:33
right, in one case it does
I'm using the optional one
SCHEMA_OPTIONAL_LINE_ITEMS
Piotr Solnica
@solnic
Jul 29 2016 21:34
wait, line items is an array or hash?
Kevin Ross
@rosskevin
Jul 29 2016 21:34
line_items: [{}]
missing .each
Piotr Solnica
@solnic
Jul 29 2016 21:37
so required(:line_items).maybe { each(LineItemSchema) } should do the trick
Kevin Ross
@rosskevin
Jul 29 2016 21:37
what if there is no line_items key
Piotr Solnica
@solnic
Jul 29 2016 21:37
then use optional instead of required
is it allowed that the value is nil?
Kevin Ross
@rosskevin
Jul 29 2016 21:38
in the optional case, no key is ok, key and no items ok
in the required case, required key, required items, length > 0
Piotr Solnica
@solnic
Jul 29 2016 21:39
ok so required(:line_items).each(LineItemSchema) and optional(:line_items).each(LineItemSchema) is all you need
Kevin Ross
@rosskevin
Jul 29 2016 21:41
wow, easier than I was trying. I think I was trying to take the hardest route possible! Thanks, this seems to work:
LINE_ITEM = Validations::Schema.new_schema(Validations::Schema.new_schema) do
  required_id(:product_id)
  required(:quantity).value(:int?, gteq?: 0)
  optional(:period_start_at).maybe(:time?)
  optional(:period_end_at).maybe(:time?)
end

SCHEMA = Validations::Schema.new_schema(BaseDocument::SCHEMA) do
  required(:line_items).each(LINE_ITEM)
end

SCHEMA_OPTIONAL_LINE_ITEMS = Validations::Schema.new_schema(BaseDocument::SCHEMA) do
  optional(:line_items).each(LINE_ITEM)
end
Piotr Solnica
@solnic
Jul 29 2016 21:42
cool :)