Dry-rb for Ruby on Rails microservice part 2: Validations

Dry-rb for Ruby on Rails microservice part 2: Validations
Average rating: 0
(0 votes)

Thanks! You’ve rated this material!

validation-dogs-209x300This is the second tech post about less persistent microservices built on Ruby on Rails with help of DRY-rb utility framework.

In the first part we’ve discussed the usage of dry-types library. Now it’s turn to show how to validate parameters with the dry-validation. With its help we are going to mimic the ActiveModel validations API.

First of all, we need to implement the the same API as ActiveModel::Validations has, that’s how it looks like:

module Validatable                                                              
extend ActiveSupport::Concern                                                 
included do                                                                   
extend ActiveModel::Naming                                                  
extend ActiveModel::Translation                                             
alias_method :attributes, :to_h                                             
end                                                                           
def read_attribute_for_validation(attr)                                       
public_send(attr)                                                           
end                                                                           
def validate!                                                                 
errors.clear                                                                
@validated = true                                                           
@validation = self.class.const_get(:Schema).call(to_h)                      
@validation.messages.each do |field, field_errors|                          
field_errors.each do |field_error|                                        
errors.add(field, field_error)                                          
end                                                                       
end                                                                         
end                                                                           
def valid?                                                                    
validate! unless @validated                                                 
@validation.success?                                                        
end                                                                           
def errors                                                                    
@_errors ||= ActiveModel::Errors.new(self)                                  
end                                                                           
end

As you can see it implements the minimal methods we used before in the traditional Rails validations: `validate!`, `valid?`, and `errors`. For the simplicity we used the ActiveModel::Errors class in favour of implementing it by our own. 🙂

Now it’s time to show how dry-validations work together with dry-types. Welcome to the Box model:

class Box < Dry::Types::Struct                                                  
include Validatable                                                           
constructor_type(:schema)                                                     
attribute :packing, Types::ZeroBox                                            
attribute :clothes, Types::ZeroBox                                            
attribute :drawings, Types::ZeroBox                                           
Schema = ::Dry::Validation.Schema do                                          
key(:packing) { int? & gteq?(0) & lteq?(100) }                               
key(:clothes) { int? & gteq?(0) & lteq?(100) }                               
key(:drawings) { int? & gteq?(0) & lteq?(100) }                             
end                                                                      
end

The Box validates `packing`, `clothes`, and `drawings` properties with these: it must be an Integer within 0 and 100. It needs some proof, so:

describe Box, type: :model do                                     
%i(packing clothes drawings).each do |field|                                  
it "validates #{field} range" do                                            
expect(described_class.new(field => '-1')).to_not be_valid                
expect(described_class.new(field => '1')).to be_valid                     
expect(described_class.new(field => 10)).to be_valid                      
expect(described_class.new(field => '101')).to_not be_valid                
end                                                                          
end                                                                           
end

If you like dry-rb, but don’t know how to use it within Rails application, that’s it!

Rate this article, if you like it

Thanks! You’ve rated this material!

Got a project? Let's discuss it!

    Kyiv Sofiivska 1/2a, 01001, Kyiv, Ukraine
    Dnipro Hlinky 2, of. 1003, 49000, Dnipro, Ukraine
    Kharkiv Otakara Yarosha 22, 61000, Kharkiv, Ukraine
    Email info@syndicode.com