Dry-валидация: не учитывает регистр валидация `includes_in?` с помощью Dry::Validation.Schema
Я пытаюсь создать проверку для заранее определенного списка действительных брендов в рамках ETL-конвейера. Моя проверка требует учета регистра, так как некоторые бренды представляют собой составные слова или сокращения, которые являются незначительными.
Я создал собственный предикат, но не могу понять, как создать соответствующее сообщение об ошибке.
Я прочитал сообщения об ошибках, но мне трудно интерпретировать:
- Как построить синтаксис для моего пользовательского предиката?
- Могу ли я применить сообщения в своем классе схемы напрямую, без ссылки на внешний файл.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 ответ
Правильный способ ссылки на мое сообщение об ошибке - ссылка на метод предиката. Не нужно беспокоиться о 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
фантастически организован, но мне трудно следовать.