Skip to content

Instantly share code, notes, and snippets.

@jodosha
Created April 1, 2016 07:21
Show Gist options
  • Save jodosha/57ff1e541e6754daa284c7621dd082a6 to your computer and use it in GitHub Desktop.
Save jodosha/57ff1e541e6754daa284c7621dd082a6 to your computer and use it in GitHub Desktop.
Hanami::Validations with DRY-V
source 'https://rubygems.org'
gem 'dry-validation'
require 'bundler/setup'
require 'dry-validation'
module Hanami
module Validations
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def self.extended(base)
base.class_eval do
@rules = Dry::Validation::Schema::Value.new
@schema = Class.new(Dry::Validation::Schema::Form)
@schema.configure {|c| c.rules = @rules.rules }
end
end
def key(name)
rules.key(name.to_sym)
end
def attr(name)
rules.attr(name.to_sym)
end
def optional(name)
rules.optional(name.to_sym)
end
def group(name, &blk)
rules.key(name.to_sym).schema(&blk)
end
def rule(name, &blk)
rules.rule(name, &blk)
end
def schema
@schema
end
private
def rules
@rules
end
end
def initialize(data)
@data = data
end
def validate
self.class.schema.new.call(@data)
end
end
end
class CreateJob
include Hanami::Validations
URL_REGEXP = URI.regexp(%w(http http)).freeze
TYPES = [1, 2, 3].freeze
group :job do
key(:type) .required(:int?, inclusion?: TYPES)
optional(:location) .maybe(:str?)
optional(:remote) .maybe(:bool?)
key(:title) .required(:str?, size?: 5..100)
optional(:description).maybe(:str?)
key(:company) .required(:str?)
key(:website) .required(:str?, format?: URL_REGEXP)
rule(location_required_if_not_remote: [:remote, :location]) do |remote, location|
remote.false?.then(location.filled?)
end
end
end
result = CreateJob.new(
job: {
type: 2, # part-time
remote: true,
title: 'Developer',
company: 'Hanami',
website: 'http://hanamirb.org'
}
).validate
puts result.success? # => true/false
puts result.messages # => Hash of errors partitioned by attribute
puts result.output # => Coerced input values
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment