gems dry-types 0.13.0

latest releases: 1.8.3, 1.8.2, 1.8.1...
7 years ago

v0.13.0 2018-05-03

Changed

  • [BREAKING] Renamed Types::Form to Types::Params. You can opt-in the former name with require 'dry/types/compat/form_types'. It will be dropped in the next release (ndrluis)
  • [BREAKING] The Int types was renamed to Integer, this was the only type named differently from the standard Ruby classes so it has been made consistent. The former name is available with require 'dry/types/compat/int' (GustavoCaso + flash-gordon)
  • [BREAKING] Default types are not evaluated on nil. Default values are evaluated only if no value were given.
      type = Types::Strict::String.default("hello")
      type[nil] # => constraint error
      type[] # => "hello"
    This change allowed to greatly simplify hash schemas, make them a lot more flexible yet predictable (see below).
  • [BREAKING] Dry::Types.register_class was removed, Dry::Types.register was made private API, do not register your types in the global dry-types container, use a module instead, e.g. Types (flash-gordon)
  • [BREAKING] Enum types don't accept value index anymore. Instead, explicit mapping is supported, see below (flash-gordon)

Added

  • Hash schemas were rewritten. The old API is still around but is going to be deprecated and removed before 1.0. The new API is simpler and more flexible. Instead of having a bunch of predefined schemas you can build your own by combining the following methods:

    1. Schema#with_key_transform—transforms keys of input hashes, for things like symbolizing etc.
    2. Schema#strict—makes a schema intolerant to unknown keys.
    3. Hash#with_type_transform—transforms member types with an arbitrary block. For instance,
    optional_keys = Types::Hash.with_type_transform { |t, _key| t.optional }
    schema = optional_keys.schema(name: 'strict.string', age: 'strict.int')
    schema.(name: "Jane", age: nil) # => {name: "Jane", age: nil}

    Note that by default all keys are required, if a key is expected to absent, add to the corresponding type's meta omittable: true:

    intolerant = Types::Hash.schema(name: Types::Strict::String)
    intolerant[{}] # => Dry::Types::MissingKeyError
    tolerant = Types::Hash.schema(name: Types::Strict::String.meta(omittable: true))
    tolerant[{}] # => {}
    tolerant_with_default = Types::Hash.schema(name: Types::Strict::String.meta(omittable: true).default("John"))
    tolerant[{}] # => {name: "John"}

    The new API is composable in a natural way:

    TOLERANT = Types::Hash.with_type_transform { |t| t.meta(omittable: true) }.freeze
    user = TOLERANT.schema(name: 'strict.string', age: 'strict.int')
    user.(name: "Jane") # => {name: "Jane"}
    
    TOLERANT_SYMBOLIZED = TOLERANT.with_key_transform(&:to_sym)
    user_sym = TOLERANT_SYMBOLIZED.schema(name: 'strict.string', age: 'strict.int')
    user_sym.("name" => "Jane") # => {name: "Jane"}

    (flash-gordon)

  • Types.Strict is an alias for Types.Instance (flash-gordon)

    strict_range = Types.Strict(Range)
    strict_range == Types.Instance(Range) # => true
  • Enum#include? is an alias to Enum#valud? (d-Pixie + flash-gordon)

  • Range was added (GustavoCaso)

  • Array types filter out Undefined values, if you have an array type with a constructor type as its member, the constructor now can return Dry::Types::Undefined to indicate empty value:

    filter_empty_strings = Types::Strict::Array.of(
      Types::Strict::String.constructor { |input|
        input.to_s.yield_self { |s| s.empty? ? Dry::Types::Undefined : s }
      }
    )
    filter_empty_strings.(["John", nil, "", "Jane"]) # => ["John", "Jane"]
  • Types::Map was added for homogeneous hashes, when only types of keys and values are known in advance, not specific key names (fledman + flash-gordon)

      int_to_string = Types::Hash.map('strict.integer', 'strict.string')
      int_to_string[0 => 'foo'] # => { 0 => "foo" }
      int_to_string[0 => 1] # Dry::Types::MapError: input value 1 for key 0 is invalid: type?(String, 1)
  • Enum supports mappings (bolshakov + flash-gordon)

    dict = Types::Strict::String.enum('draft' => 0, 'published' => 10, 'archived' => 20)
    dict['published'] # => 'published'
    dict[10] # => 'published'

Fixed

  • Fixed applying constraints to optional type, i.e. .optional.constrained works correctly (flash-gordon)
  • Fixed enum working with optionals (flash-gordon)

Internal

  • Dropped the dry-configurable dependency (GustavoCaso)
  • The gem now uses dry-inflector for inflections instead of inflecto (GustavoCaso)

Compare v0.12.2...v0.13.0

Don't miss a new dry-types release

NewReleases is sending notifications on new releases.