Skip to content

Better handling of splatted keyword arguments and with_collection #2020

@daniel-rikowski

Description

@daniel-rikowski

Feature request

Allow components to have unnamed keyword arguments when using with_collection

Motivation

This would allow using generic initialize methods with unnamed parameters and provide more flexible opportunities for composition, especially in regards of DRYing up initializers.

Also, I can imagine, this would become a necessity with #2004

Details

Currently these scenarious are not possible:

Example 1: (concept from ViewComponentContrib)

class ApplicationViewComponent < ViewComponent::Base
  extend Dry::Initializer[undefined: false]
end

class ButtonComponent < ApplicationViewComponent
  option :button

  erb_template <<~ERB
    <%= button.inspect %>
  ERB
end

NB: extend Dry::Initializer adds this method definition:

def initialize(...)
  __dry_initializer_initialize__(...)
end

(... is verbatim Ruby code)

Example 2: (meta programming)

module InitHelpers
  extend ActiveSupport::Concern

  class_methods do
    def record_name = name.demodulize.underscore.chomp("_component").to_sym
  end

  included do
    attr_reader self.record_name
  end

  def init_component(**options)
    attr = self.class.record_name
    instance_variable_set(:"@#{attr}", options[attr])
  end
end

class AvatarComponent < ViewComponent::Base
  include InitHelpers

  def initialize(**)
    init_component(**)
  end

  erb_template <<~ERB
    <%= avatar.inspect %>
  ERB
end

There is an explicit check to exclude unnamed keyword arguments:

def splatted_keyword_argument_present?
initialize_parameters.flatten.include?(:keyrest) &&
!initialize_parameters.include?([:keyrest, :**]) # Un-named splatted keyword args don't count!
end

I did some rummaging and found this commit 56a6560 It mentions that Ruby 3.1 def m(*) might implicitly be the same as def m(*,**)

If that's actually the case it does make sense to forbid unnamed splatted kwargs, but I assume this check can be relaxed for other Ruby versions.

PR

I'm happy to make a PR, but first I want to discuss the proper way to do this, especially considering the fact, that removing the check might introduce subtle bugs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions