Sha256: 12ad1306b014c5e5a1a14c8012275ee030e43f5403db0a87e793c2c46ccb0415

Contents?: true

Size: 1.56 KB

Versions: 1

Compression:

Stored size: 1.56 KB

Contents

# frozen_string_literal: true

class Micro::Struct::Creator
  module CreateModule
    extend self

    def with(required_members, optional_members, features)
      container = Module.new

      def_initialize_and_members(container, required_members, optional_members)

      def_to_proc(container) if features[:to_proc]

      container
    end

    private

      def def_initialize_and_members(container, required_members, optional_members)
        required = "#{required_members.join(':, ')}#{':' unless required_members.empty?}"
        optional = "#{optional_members.join(': nil, ')}#{': nil' unless optional_members.empty?}"

        method_arguments = [required, optional].reject(&:empty?).join(', ')
        struct_arguments = (required_members + optional_members).join(', ')

        container.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
          # The .new() method will require all required keyword arguments.
          # We are doing this because the Struct constructor keyword init option treats everything as optional.
          #
          def self.new(#{method_arguments})        # def self.new(a:, b:) do
            Struct.send(:new, #{struct_arguments}) #   Struct.send(:new, a, b)
          end                                      # end

          def self.members
            Struct.members
          end
        RUBY
      end

      def def_to_proc(container)
        container.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
          def self.to_proc
            ->(hash) { new(**hash) }
          end
        RUBY
      end
  end

  private_constant :CreateModule
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
u-struct-0.7.0 lib/micro/struct/creator/create_module.rb