author avatar

ayushsrivastava

Mon Jan 22 2024

While creating contracts using Dry Gem it is important to keep in mind that if a validation rule is independent of a key from schema then schema will not process those keys before executing the validation rule.

For Example

class RoomAvailabilityFormContract < Dry::Validation::Contract
  params do
    required(:date_from).filled(:string)
    required(:date_to).filled(:string)
  end

  rule(:date_to) do
    date_from = Date.parse(values[:date_from]) 
    date_to = Date.parse(values[:date_to])

    if date_to && date_from && date_to <= date_from
      key.failure('date_to must be ahead of date_from')
    end
  end
end

Our expectation from above contract will be if either date_to or date_from is missing in the schema the rule should not be executed and error should be caught while schema processes the keys which are date_to and date_from

But it will only work in case of date_from because the validation rule is dependent on the date_from key so if we have date_to as nil the rule will still be executed and might cause other errors like in our trying to parse nil value which does not fulfills the purpose of this gem.

To not get into such errors we should make sure that the validation rules are dependent upon the keys that are validated in schema

So the fix in above code will be to include date_to

rule(:date_from, :date_to) do
    date_from = Date.parse(values[:date_from]) 
    date_to = Date.parse(values[:date_to])

    if date_to && date_from && date_to <= date_from
      key.failure('date_to must be ahead of date_from')
    end
  end

now before implementing the rule the schema will first validate both the keys and throw error if the values are not abiding to the schema