0.13.2 regression - Error messages that include input values are improperly cached when using I18n backend

Hi,

After updating dry-validation from 0.13.1 to 0.13.2 one of my tests started failing. It seems that when using I18n backend, the error messages caching mechanism ignores changes to the values of the input passed to the schema / contract. Ie., it caches the first value that was used and uses it for subsequent message instances.

Below you can find simplest possible case where this behaviour can be observed. As you can see, when I18n backend is enabled, both error messages are the same, even though the input is different.

It can be reproduced for both built-in and custom predicates (I haven’t checked rules, though). When I18n is not enabled, everything seems to work fine.

  • Gemfile:

    source 'https://rubygems.org'
    
    gem 'i18n', '1.6.0'
    gem 'dry-validation', '0.13.2'
    
  • errors.yml

    en:
      errors:
        gt?:
          arg:
            default: "%{input} must be greater than %{num}"
    
  • test.rb

    schema = Dry::Validation.Schema do
      configure do
        config.messages      = :i18n
        config.messages_file = 'errors.yml'
      end
    
      required(:age).value(gt?: 100)
    end
    
    # Without `config.messages = :i18n`
    puts schema.call(age: 1).messages  # => {:age=>["1 must be greater than 50"]}
    puts schema.call(age: 47).messages # => {:age=>["47 must be greater than 50"]}
    
    # With `config.messages = :i18n`
    puts schema.call(age: 1).messages  # => {:age=>["1 must be greater than 50"]}
    puts schema.call(age: 47).messages # => {:age=>["1 must be greater than 50"]}
    

It can be reproduced on master, too:

  • Gemfile

    source 'https://rubygems.org'
    
    gem 'i18n', '1.6.0'
    gem 'dry-validation', git: 'https://github.com/dry-rb/dry-validation'
    
  • errors.yml

    en:
      dry_validation:
        errors:
          gt?:
            arg:
              default: "%{input} must be greater than %{num}"
    
  • test.rb

    class Contract < Dry::Validation::Contract
      config.messages.backend = :i18n
      config.messages.load_paths << 'errors.yml'
    
      params do
        required(:age).value(gt?: 100)
      end
    end
    
    # Without `config.messages.backend = :i18n`
    puts Contract.new.call(age: 1).errors.messages  # => "1 must be greater than 100"
    puts Contract.new.call(age: 47).errors.messages # => "47 must be greater than 100"
    
    # With `config.messages.backend = :i18n`
    puts Contract.new.call(age: 1).errors.messages  # => "1 must be greater than 100"
    puts Contract.new.call(age: 47).errors.messages # => "1 must be greater than 100"
    

Cheers,
Karol

Thanks for reporting this. I’ll be fixing it tomorrow.

This was fixed in https://rubygems.org/gems/dry-validation/versions/0.13.3

Thanks for fixing this!

1 Like