Automatically truncate a string

285 views Asked by At

Taking the example from dry-validation:

require "dry-validation"

module Types
  include Dry::Types.module

  Name = Types::String.constructor do |str|
    str ? str.strip.chomp : str
  end
end

SignUpForm = Dry::Validation.Params do
  configure do
    config.type_specs = true
  end

  required(:code, Types::StrictString).filled(max_size?: 4)
  required(:name, Types::Name).filled(min_size?: 1)
  required(:password, :string).filled(min_size?: 6)
end

result = SignUpForm.call(
  "name" => "\t François \n",
  "code" => "francois",
  "password" => "some password")

result.success?
# true

# This is what I WANT
result[:code]
# "fran"

I would like to create a new Type, StrictString that will use the predicate information, like max_size and truncate it.

The problem: I don't have access to the predicates in the Types::String.constructor. If I go the other way around, ie, via a custom predicate, I can't only return true or false, I cannot see how can I change the argument.

Am I trying to kill a fly with a shotgun?

1

There are 1 answers

0
Paulo Fidalgo On

Following a tip by the dry-types creator I've managed to create a new Type that can be used:

# frozen_string_literal: true

require 'dry-types'

module Types
  include Dry::Types.module

  # rubocop:disable Naming/MethodName
  def self.TruncatedString(size)
    Types::String.constructor { |s| s[0..size - 1] unless s.nil? }.constrained(max_size: size)
  end
  # rubocop:enable Naming/MethodName
end

So now I can use:

attribute :company_name, Types::TruncatedString(100)

instead of:

attribute :company_name, Types::String.constrained(max_size: 100)