I would like to migrate some of my View component to dry-initializer. A typical patter I have (largely inspired by Github primer view component is to declare a few named attributes and get a generic **kwargs that will collect all remaining arguments passed to the component
example :
def initialize(color: :primary, **kwargs)
@color = color
@kwargs = kwargs
end
is there a ways to do the same with dry intializer ? How can I access to extra kwargs provided ?
here is one solution that was suggested to me
require "dry-initializer"
class HelloWorld
extend ::Dry::Initializer
option :color, default: proc { :primary }
attr_accessor :kwargs
def initialize(*args, **kwargs)
super(args, kwargs)
@kwargs = kwargs.tap { self.class.dry_initializer.attributes(self).keys.each { |key| kwargs.delete(key)} } || {}
end
def print
puts "@color: #{color}"
puts "@kwargs: #{kwargs}"
end
end
HelloWorld.new(color: :secondary, other: "yo").print
HelloWorld.new(kwarg: :yo).print
HelloWorld.new.print
This is not directly supported in the gem but you can accomplish it yourself
class Component
extend Dry::Initializer
option :foo
option :bar
option :kwargs
def initialize(**options)
defined = self.class.dry_initializer.options.map(&:target)
kwargs = options.except(*defined)
options = options.except(*kwargs.keys)
kwargs.merge!(options.delete(:kwargs)) if options.key?(:kwargs)
super(kwargs:, **options)
end
end
3 Likes