Создание вложенных/повторно используемых валидаторов в Ruby с сухой проверкой

Допустим, я хочу настроить валидационный контракт для адресов, но затем я также хочу настроить валидатор для пользователей и для кофеен; оба из которых включают адрес, возможно ли повторно использовать AddressContractв UserContractа также CoffeeShopContract?

Например, данные, которые я хочу проверить, могут выглядеть так:

      # Address
{
    "first_line": "100 Main street",
    "zipcode": "12345",
}

# User
{
    "first_name": "Joe",
    "last_name": "Bloggs",
    "address:" {
        "first_line": "123 Boulevard",
        "zipcode": "12346",
    }
}

# Coffee Shop
{
    "shop": "Central Perk",
    "floor_space": "2000sqm",
    "address:" {
        "first_line": "126 Boulevard",
        "zipcode": "12347",
    }
}

1 ответ

Да, вы можете повторно использовать схемы (см. Повторное использование схем )

Это будет выглядеть примерно так:

      require 'dry/validation'
class AddressContract < Dry::Validation::Contract 
  params do 
    required(:first_line).value(:string) 
    required(:zipcode).value(:string) 
  end
end

class UserContract < Dry::Validation::Contract 
  params do
    required(:first_name).value(:string)
    required(:last_name).value(:string)
    required(:address).schema(AddressContract.schema)
  end
end 


a = {first_line: '123 Street Rd'}
u = {first_name: 'engineers', last_name: 'mnky', address: a }

AddressContract.new.(a)
#=> #<Dry::Validation::Result{:first_line=>"123 Street Rd"} errors={:zipcode=>["is missing"]}>
UserContract.new.(u)
#=> #<Dry::Validation::Result{:first_name=>"engineers", :last_name=>"mnky", :address=>{:first_line=>"123 Street Rd"}} errors={:address=>{:zipcode=>["is missing"]}}>

В качестве альтернативы вы также можете создавать миксины схемы, например

      AddressSchema = Dry::Schema.Params do 
  required(:first_line).value(:string) 
  required(:zipcode).value(:string) 
end 

class AddressContract < Dry::Validation::Contract 
    params(AddressSchema) 
end

class UserContract < Dry::Validation::Contract 
  params do
    required(:first_name).value(:string)
    required(:last_name).value(:string)
    required(:address).schema(AddressSchema)
  end
end 
Другие вопросы по тегам