This was originally a GitHub issue, now moved here for discussion
User Story
As a developer I’d like to be able to access
- [ ] call type objects with class methods
- [ ] call class methods even when
Dry::Types
is aliased toTypes
So the code is more readable, & less typing for the developer.
Examples
module Types
include Dry.Types()
end
# old
drinking_age = Types::Integer.constrained(gt: 21)
# new
drinking_age = Dry::Types.integer.constrained(gt: 21)
# old
email = Dry::Types::String.constrained(
format: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
)
email = Dry::Types.string.constrained(
format: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
)
Not a huge difference, right? But once you’ve alias Types
, your code changes:
# from this
drinking_age = Dry::Types::Integer.constrained(gt: 21)
# to this
drinking_age = Types.integer.constrained(gt: 21)
# or if you need more specificity
drinking_age = Types.send('coerible.integer').constrained(gt: 21)
6 characters less, and more readable (in my opinion).
Here’s a working of how I updated my tinder_client gem from using Dry::Types['string']
to Types.string
:
class Updates < Dry::Struct
- attribute :blocks, Dry::Types['array'].of(Dry::Types['string'])
- attribute :deleted_lists, Dry::Types['array']
- attribute :goingout, Dry::Types['array']
- attribute :harassing_messages, Dry::Types['array']
- attribute :inbox, Dry::Types['array'] do
- attribute :_id, Dry::Types['string']
- attribute :match_id, Dry::Types['string']
- attribute :sent_date, Dry::Types['string']
- attribute :message, Dry::Types['string']
- attribute :to, Dry::Types['string']
- attribute :from, Dry::Types['string']
- attribute :created_date, Dry::Types['string']
- attribute :timestamp, Dry::Types['coercible.string']
+ attribute :blocks, Types.array.of(Types.string)
+ attribute :deleted_lists, Types.array
+ attribute :goingout, Types.array
+ attribute :harassing_messages, Types.array
+ attribute :inbox, Types.array do
+ attribute :_id, Types.string
+ attribute :match_id, Types.string
+ attribute :sent_date, Types.string
+ attribute :message, Types.string
+ attribute :to, Types.string
+ attribute :from, Types.string
+ attribute :created_date, Types.string
+ attribute :timestamp, Types.send('coercible.string')
end
end
end
Resources
The way I’m able to accomplish this was by taking the existing snippet from the dry-types
docs to create a Types
module, then add all the type keys as methods:
spec_helper.rb
require 'dry-types'
require 'dry-struct'
# This automatically transforms keys to symbols when you pass Structs a hash
# that has string keys
class Dry::Struct
transform_keys(&:to_sym)
end
# The following allow you to access types with Types.<type reference>
#
# ```ruby
# email = Types.string.constrained(
# format: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
# )
# drinking_age = Types.integer.constrained(gt: 21)
# ````
module Types
include Dry.Types()
class << self
# @param String The key of the Dry::Type -- see Dry::Types.type_keys
def [] (type_key)
Dry::Types[type_key]
end
# This aliases all the Dry::Types keys as class methods
Dry::Types.type_keys.each do |method_name|
define_method method_name do
Dry::Types[method_name]
end
end
end
end
@flash-gordon @solnic please take a look thanks