Ruby 2.5未満でRuby 2.5のStructのkeyword_initを使う

追記: backports v3.11.0の時点ではstruct/new.rbの冒頭に変なputsがあるなど使われている形跡がありません。またフィールド名を予約語にすると使えないという問題もありました。一旦自前のmonkey patchを使うことにしてます。

NEWS-2.5.0 - Documentation for Ruby trunk

Struct.new takes keyword_init: true option to initialize members with keyword arguments. [Feature #11925]

これですね。

こんな感じのモンキーパッチでいけそうです。

# frozen_string_literal: true

# Backport Ruby 2.5's `keyword_init: true`
module Ruby25StructExtension
  module ClassMethods
    def new(*args, keyword_init: false, &block)
      super(*args) do
        if keyword_init
          define_method(:initialize) do |**kwargs|
            super(*members.map { |k| kwargs[k] })
          end
        end

        if block
          class_eval(&block)
        end
      end
    end
  end
end


if RUBY_VERSION < "2.5.0"
  Struct.singleton_class.prepend(Ruby25StructExtension::ClassMethods)
end

実装したあとで、そういえばbackports gemがあったなと思って確認すると実装済でした😇

backports/new.rb at master · marcandre/backports · GitHub

なのでRuby 2.5未満で keyword_init が欲しければ(そして他のRuby 2.5で追加されたメソッドも!)backports gemを使えばいいですね。