diff --git a/docsite/source/array-with-member.html.md b/docsite/source/array-with-member.html.md index 67c4a810..c3d9437f 100644 --- a/docsite/source/array-with-member.html.md +++ b/docsite/source/array-with-member.html.md @@ -7,6 +7,8 @@ name: dry-types The built-in array type supports defining the member's type: ``` ruby +Types = Dry.Types() + PostStatuses = Types::Array.of(Types::Coercible::String) PostStatuses[[:foo, :bar]] # ["foo", "bar"] diff --git a/docsite/source/built-in-types.html.md b/docsite/source/built-in-types.html.md index 0c5c2c75..10aad11c 100644 --- a/docsite/source/built-in-types.html.md +++ b/docsite/source/built-in-types.html.md @@ -15,7 +15,7 @@ Built-in types are grouped under 6 categories: ### Categories -Assuming you included `Dry::Types` ([see instructions](docs::getting-started)) in a module called `Types`: +Assuming you've defined your own `Types` module ([see instructions](docs::getting-started)): * Nominal types: - `Types::Nominal::Any` diff --git a/docsite/source/constraints.html.md b/docsite/source/constraints.html.md index 60665814..7b24de77 100644 --- a/docsite/source/constraints.html.md +++ b/docsite/source/constraints.html.md @@ -11,6 +11,8 @@ All types support the constraints API, but not all constraints are suitable for Under the hood it uses [`dry-logic`](/gems/dry-logic) and all of its predicates are supported. ``` ruby +Types = Dry.Types() + string = Types::String.constrained(min_size: 3) string['foo'] diff --git a/docsite/source/custom-types.html.md b/docsite/source/custom-types.html.md index 5d5a8c24..d8337cf2 100644 --- a/docsite/source/custom-types.html.md +++ b/docsite/source/custom-types.html.md @@ -11,6 +11,8 @@ There are a bunch of helpers for building your own types based on existing class `Types.Instance` builds a type that checks if a value has the given class. ```ruby +Types = Dry.Types() + range_type = Types.Instance(Range) range_type[1..2] # => 1..2 ``` @@ -20,6 +22,8 @@ range_type[1..2] # => 1..2 `Types.Value` builds a type that checks a value for equality (using `==`). ```ruby +Types = Dry.Types() + valid = Types.Value('valid') valid['valid'] # => 'valid' valid['invalid'] @@ -31,6 +35,8 @@ valid['invalid'] `Types.Constant` builds a type that checks a value for identity (using `equal?`). ```ruby +Types = Dry.Types() + valid = Types.Constant(:valid) valid[:valid] # => :valid valid[:invalid] @@ -42,6 +48,8 @@ valid[:invalid] `Types.Constructor` builds a new constructor type for the given class. By default uses the `new` method as a constructor. ```ruby +Types = Dry.Types() + user_type = Types.Constructor(User) # It is equivalent to User.new(name: 'John') @@ -59,6 +67,8 @@ user_type = Types.Constructor(User) { |values| User.new(values) } `Types.Nominal` wraps the given class with a simple definition without any behavior attached. ```ruby +Types = Dry.Types() + int = Types.Nominal(Integer) int[1] # => 1 @@ -71,6 +81,8 @@ int['one'] # => 'one' `Types.Hash` builds a new hash schema. ```ruby +Types = Dry.Types() + # In the full form Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer) @@ -83,6 +95,8 @@ Types.Hash(name: Types::String, age: Types::Coercible::Integer) `Types.Array` is a shortcut for `Types::Array.of` ```ruby +Types = Dry.Types() + ListOfStrings = Types.Array(Types::String) ``` @@ -91,6 +105,8 @@ ListOfStrings = Types.Array(Types::String) `Types.Interface` builds a type that checks a value responds to given methods. ```ruby +Types = Dry.Types() + Callable = Types.Interface(:call) Contact = Types.Interface(:name, :phone) -``` \ No newline at end of file +``` diff --git a/docsite/source/default-values.html.md b/docsite/source/default-values.html.md index 2a8a7964..bc049563 100644 --- a/docsite/source/default-values.html.md +++ b/docsite/source/default-values.html.md @@ -7,6 +7,8 @@ name: dry-types A type with a default value will return the configured value when the input is not defined: ``` ruby +Types = Dry.Types() + PostStatus = Types::String.default('draft') PostStatus[] # "draft" diff --git a/docsite/source/enum.html.md b/docsite/source/enum.html.md index eeb82313..58c2cfd0 100644 --- a/docsite/source/enum.html.md +++ b/docsite/source/enum.html.md @@ -10,9 +10,7 @@ In many cases you may want to define an enum. For example, in a blog application require 'dry-types' require 'dry-struct' -module Types - include Dry.Types() -end +Types = Dry.Types() class Post < Dry::Struct Statuses = Types::String.enum('draft', 'published', 'archived') @@ -41,11 +39,13 @@ Post::Statuses[nil] Note that if you want to define an enum type with a default, you must call `.default` *before* calling `.enum`, not the other way around: ```ruby +Types = Dry.Types() + # this is the correct usage: -Dry::Types::String.default('red').enum('blue', 'green', 'red') +Types::String.default('red').enum('blue', 'green', 'red') # this will raise an error: -Dry::Types::String.enum('blue', 'green', 'red').default('red') +Types::String.enum('blue', 'green', 'red').default('red') ``` ### Mappings @@ -53,11 +53,12 @@ Dry::Types::String.enum('blue', 'green', 'red').default('red') A classic example is mapping integers coming from somewhere (API/database/etc) to something more understandable: ```ruby +Types = Dry.Types() + class Cell < Dry::Struct attribute :state, Types::String.enum('locked' => 0, 'open' => 1) end - Cell.new(state: 'locked') # => # diff --git a/docsite/source/extensions.html.md b/docsite/source/extensions.html.md index 6d5d85f4..c54d0994 100644 --- a/docsite/source/extensions.html.md +++ b/docsite/source/extensions.html.md @@ -7,7 +7,7 @@ sections: - monads --- -`dry-types` can be extended with extension. Those extensions are loaded with `Dry::Types.load_extensions`. +dry-types can be extended with extension. Those extensions are loaded with `Dry::Types.load_extensions`. Available extensions: diff --git a/docsite/source/extensions/maybe.html.md b/docsite/source/extensions/maybe.html.md index adb9f356..ff220abc 100644 --- a/docsite/source/extensions/maybe.html.md +++ b/docsite/source/extensions/maybe.html.md @@ -13,12 +13,11 @@ The [dry-monads gem](/gems/dry-monads/) provides approach to handling optional v require 'dry-types' Dry::Types.load_extensions(:maybe) -module Types - include Dry.Types() -end + +Types = Dry.Types() ``` -2. Append `.maybe` to a _Type_ to return a _Monad_ object +2. Append `.maybe` to a _Type_ to return a _Monad_ object ```ruby x = Types::Maybe::Strict::Integer[nil] diff --git a/docsite/source/getting-started.html.md b/docsite/source/getting-started.html.md index a2f4fb7d..09ca8d97 100644 --- a/docsite/source/getting-started.html.md +++ b/docsite/source/getting-started.html.md @@ -4,24 +4,22 @@ layout: gem-single name: dry-types --- -### Using `Dry::Types` in Your Application +### Using dry-types in your application -1. Make `Dry::Types` available to the application by creating a namespace that includes `Dry::Types`: +1. Make the base types available to your application by defining your own module built from `Dry.Types()`: ```ruby - module Types - include Dry.Types() - end + Types = Dry.Types() ``` - -2. Reload the environment, & type `Types::Coercible::String` in the ruby console to confirm it worked: + +2. Reload the environment, & enter `Types::Coercible::String` in your ruby console to confirm it worked: ``` ruby Types::Coercible::String - # => #> + # => # fn=Kernel.String>]> ``` -### Creating Your First Type +### Creating your first type 1. Define a struct's types by passing the name & type to the `attribute` method: @@ -31,15 +29,16 @@ name: dry-types end ``` -2. Define [Custom Types](docs::custom-types) in the `Types` module, then pass the name & type to `attribute`: +2. Define [Custom Types](docs::custom-types) in your types module, then pass the name & type to `attribute`: ```ruby + Types = Dry.Types() + module Types - include Dry.Types() - Email = String.constrained(format: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i) Age = Integer.constrained(gt: 18) end + class User < Dry::Struct attribute :name, Types::String attribute :email, Types::Email diff --git a/docsite/source/hash-schemas.html.md b/docsite/source/hash-schemas.html.md index 5c628d75..6a5f35c4 100644 --- a/docsite/source/hash-schemas.html.md +++ b/docsite/source/hash-schemas.html.md @@ -7,6 +7,8 @@ name: dry-types It is possible to define a type for a hash with a known set of keys and corresponding value types. Let's say you want to describe a hash containing the name and the age of a user: ```ruby +Types = Dry.Types() + # using simple kernel coercions user_hash = Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer) @@ -78,6 +80,8 @@ The process of converting types to constructors like that can be automated, see By default, all keys are required to present in the input. You can mark a key as optional by adding `?` to its name: ```ruby +Types = Dry.Types() + user_hash = Types::Hash.schema(name: Types::String, age?: Types::Integer) user_hash[name: 'Jane'] @@ -89,6 +93,8 @@ user_hash[name: 'Jane'] All keys not declared in the schema are silently ignored. This behavior can be changed by calling `.strict` on the schema: ```ruby +Types = Dry.Types() + user_hash = Types::Hash.schema(name: Types::String).strict user_hash[name: 'Jane', age: 21] # => Dry::Types::UnknownKeysError: unexpected keys [:age] in Hash input @@ -99,6 +105,8 @@ user_hash[name: 'Jane', age: 21] Keys are supposed to be symbols but you can attach a key tranformation to a schema, e.g. for converting strings into symbols: ```ruby +Types = Dry.Types() + user_hash = Types::Hash.schema(name: Types::String).with_key_transform(&:to_sym) user_hash['name' => 'Jane'] @@ -110,6 +118,8 @@ user_hash['name' => 'Jane'] Hash schemas can be inherited in a sense you can define a new schema based on an existing one. Declared keys will be merged, key and type transformations will be preserved. The `strict` option is also passed to the new schema if present. ```ruby +Types = Dry.Types() + # Building an empty base schema StrictSymbolizingHash = Types::Hash.schema({}).strict.with_key_transform(&:to_sym) @@ -131,6 +141,8 @@ The resulting schema will have the sum of both sets of attributes. ```ruby +Types = Dry.Types() + user_hash = Types::Hash.schema( name: Types::String ) @@ -153,6 +165,8 @@ while each attribute keeps the type transformations from its original hash. A schema can transform types with a block. For example, the following code makes all keys optional: ```ruby +Types = Dry.Types() + user_hash = Types::Hash.with_type_transform { |type| type.required(false) }.schema( name: Types::String, age: Types::Integer diff --git a/docsite/source/index.html.md b/docsite/source/index.html.md index 75e7a128..70e457f6 100644 --- a/docsite/source/index.html.md +++ b/docsite/source/index.html.md @@ -20,7 +20,7 @@ sections: - extensions --- -`dry-types` is a simple and extendable type system for Ruby; useful for value coercions, applying constraints, defining complex structs or value objects and more. It was created as a successor to [Virtus](https://github.com/solnic/virtus). +dry-types is a simple and extendable type system for Ruby; useful for value coercions, applying constraints, defining complex structs or value objects and more. It was created as a successor to [Virtus](https://github.com/solnic/virtus). ### Example usage @@ -28,9 +28,7 @@ sections: require 'dry-types' require 'dry-struct' -module Types - include Dry.Types() -end +Types = Dry.Types() User = Dry.Struct(name: Types::String, age: Types::Integer) @@ -111,7 +109,7 @@ User.schema.key(:age).meta # => {:info=>"extra info about age"} ``` -- Pass values directly to `Dry::Types` without creating an object using `[]`: +- Pass values directly to types without creating an object using `[]`: ```ruby Types::Strict::String["foo"] @@ -142,7 +140,7 @@ Types::Strict::String[10000] ### Use cases -`dry-types` is suitable for many use-cases, for example: +dry-types is suitable for many use-cases, for example: * Value coercions * Processing arrays @@ -152,7 +150,7 @@ Types::Strict::String[10000] ### Other gems using dry-types -`dry-types` is often used as a low-level abstraction. The following gems use it already: +dry-types is often used as a low-level abstraction. The following gems use it already: * [dry-struct](/gems/dry-struct) * [dry-initializer](/gems/dry-initializer) diff --git a/docsite/source/map.html.md b/docsite/source/map.html.md index 839b8a03..ada9f84e 100644 --- a/docsite/source/map.html.md +++ b/docsite/source/map.html.md @@ -7,6 +7,8 @@ name: dry-types `Map` describes a homogeneous hashmap. This means only types of keys and values are known. You can simply imagine a map input as a list of key-value pairs. ```ruby +Types = Dry.Types() + int_float_hash = Types::Hash.map(Types::Integer, Types::Float) int_float_hash[100 => 300.0, 42 => 70.0] # => {100=>300.0, 42=>70.0} diff --git a/docsite/source/optional-values.html.md b/docsite/source/optional-values.html.md index 1f667cc1..cc477c7f 100644 --- a/docsite/source/optional-values.html.md +++ b/docsite/source/optional-values.html.md @@ -6,11 +6,13 @@ name: dry-types Types themselves have optional attributes you can apply to get further functionality. -### Append `.optional` to a _Type_ to allow `nil` +### Append `.optional` to a type to allow `nil` By default, nil values raise an error: ``` ruby +Types = Dry.Types() + Types::Strict::String[nil] # => raises Dry::Types::ConstraintError ``` @@ -30,6 +32,6 @@ optional_string[123] `Types::String.optional` is just syntactic sugar for `Types::Strict::Nil | Types::Strict::String`. -### Handle optional values using Monads +### Handle optional values using monads -See [Maybe](docs::extensions/maybe) extension for another approach to handling optional values by returning a [_Monad_](/gems/dry-monads/) object. +See the [Maybe](docs::extensions/maybe) extension for another approach to handling optional values by returning a [_monad_](/gems/dry-monads/) object. diff --git a/docsite/source/sum.html.md b/docsite/source/sum.html.md index fe2f4661..ae90e4c8 100644 --- a/docsite/source/sum.html.md +++ b/docsite/source/sum.html.md @@ -7,11 +7,13 @@ order: 7 You can specify sum types using `|` operator, it is an explicit way of defining what the valid types of a value are. -For example `dry-types` defines the `Bool` type which is a sum consisting of the `True` and `False` types, expressed as `Types::True | Types::False`. +For example dry-types defines the `Bool` type which is a sum consisting of the `True` and `False` types, expressed as `Types::True | Types::False`. Another common case is defining that something can be either `nil` or something else: ``` ruby +Types = Dry.Types() + nil_or_string = Types::Nil | Types::String nil_or_string[nil] # => nil