Having the following class:
class URL < Dry::Struct
attr_reader :description
attr_reader :url
def initialize(description:, url:)
@description = description
@url = url
end
end
And the code:
example_url = URL.new(description: "Example website", url: "https://example.com")
Fails with:
`initialize': wrong number of arguments (given 1, expected 0; required keywords: description, url) (ArgumentError)
Is it expected? Are keyword arguments not supported when using dry-struct?
Keyword arguments work fine, you’re having trouble because you’re not using the struct interface at all.
require 'dry/types'
require 'dry/struct'
require 'uri'
Types = Dry.Types(default: :strict)
module Types
URL = Instance(URI::Generic).constructor { URI(_1) }
end
class URL < Dry::Struct
attribute :description, Types::String
attribute :url, Types::URL
end
URL.new(description: "Example website", url: "https://example.com")
# => #<URL description="Example website" url=#<URI::HTTPS https://example.com>>
1 Like
The more involved answer to your question is that defining your own initialize
is almost never necessary, and what you are trying to do in the example would not work.
Struct::new
collects the incoming attributes and performs a schema validation against your ::schema
object (try inspecting URL.schema
to see it). Anything that has not been declared with attribute
will be discarded before initialize
is even called.
So if you actually wanted to implement initialize
, first of all you need to call super
. And secondly, it will receive a single hash of attributes because that is the output of the schema validation.
1 Like