Dry-валидация: не учитывает регистр валидация `includes_in?` с помощью Dry :: Validation.Schema - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь создать проверку для заранее определенного списка допустимых брендов в рамках ETL-конвейера.Моя проверка требует нечувствительности к регистру, так как некоторые бренды представляют собой составные слова или сокращения, которые не имеют значения.

Я создал собственный предикат, но не могу понять, как создать соответствующее сообщение об ошибке.

Iпрочитайте сообщения об ошибках doc , но мне сложно интерпретировать:

  • Как создать синтаксис для моего пользовательского предиката?
  • Можно ли применить сообщенияв моем классе схемы напрямую, без ссылки на внешний файл .yml?Я посмотрел здесь и кажется, что это не так просто, как я надеялся.

Ниже я привел код, который представляет то, что я пробовал, используя оба встроенных предикатаи пользовательский, каждый со своими проблемами.Если есть лучший способ составить правило, которое достигает той же цели, я бы с удовольствием его изучил.

require 'dry/validation'

CaseSensitiveSchema = Dry::Validation.Schema do
  BRANDS = %w(several hundred valid brands)

  # :included_in? from https://dry-rb.org/gems/dry-validation/basics/built-in-predicates/
  required(:brand).value(included_in?: BRANDS)
end

CaseInsensitiveSchema = Dry::Validation.Schema do
  BRANDS = %w(several hundred valid brands)

  configure do
    def in_brand_list?(value)
      BRANDS.include? value.downcase
    end
  end

  required(:brand).value(:in_brand_list?)
end


# A valid string if case insensitive
valid_product = {brand: 'Valid'}

CaseSensitiveSchema.call(valid_product).errors
# => {:brand=>["must be one of: here, are, some, valid, brands"]} # This message will be ridiculous when the full brand list is applied

CaseInsensitiveSchema.call(valid_product).errors
# => {}   # Good!



invalid_product = {brand: 'Junk'}

CaseSensitiveSchema.call(invalid_product).errors
# => {:brand=>["must be one of: several, hundred, valid, brands"]}  # Good... (Except this error message will contain the entire brand list!!!)

CaseInsensitiveSchema.call(invalid_product).errors
# => Dry::Validation::MissingMessageError: message for in_brand_list? was not found
# => from .. /gems/2.5.0/gems/dry-validation-0.12.2/lib/dry/validation/message_compiler.rb:116:in `visit_predicate'

1 Ответ

0 голосов
/ 20 ноября 2018

Правильный способ ссылки на мое сообщение об ошибке - ссылка на метод предиката. Не нужно беспокоиться о arg, value и т. Д.

en:
  errors:
    in_brand_list?: "must be in the master brands list"

Кроме того, я смог загрузить это сообщение об ошибке без отдельного .yml, выполнив это:

CaseInsensitiveSchema = Dry::Validation.Schema do
  BRANDS = %w(several hundred valid brands)

  configure do
    def in_brand_list?(value)
      BRANDS.include? value.downcase
    end

    def self.messages
      super.merge({en: {errors: {in_brand_list?: "must be in the master brand list"}}})
    end     
  end

  required(:brand).value(:in_brand_list?)
end

Я бы все еще хотел бы увидеть другие реализации, особенно для общего предиката без учета регистра. Многие говорят, что dry-rb фантастически организовано, но мне трудно следовать.

...