Define_method with predefined keyword arguments

I want to define a method that takes keyword arguments. I'd like this to be promoted when no keyword arguments were provided and I can do it myself, but ideally I'd like to let Ruby do it for me. Also I would like to be able to test the method I just defined using Method#parameters

. If I use the abbreviated double sign (for example **kwargs

), the actual structure I expect is not visible parameters

.

I can of course do this:

define_method(:foo) do | foo:, bar: |
  # ...
end

      

which achieves the desired result:

method(:foo).parameters
# => [[:keyreq, :foo], [:keyreq, :bar]]

      

but I cannot pass these arguments programmatically, they have to be literally put into the code. Is there a way to get around this?

+3


source to share


1 answer


You should use eval

to define arguments dynamically (not just keyword arguments) eg. using class_eval

:



class MyClass
  name = :foo
  args = [:bar, :baz]
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
    def #{name}(#{args.map { |a| "#{a}:" }.join(', ')}) # def foo(bar:, baz:)
      [#{args.join(', ')}]                              #   [bar, baz]
    end                                                 # end
  METHOD
end

MyClass.new.foo(bar: 1, baz: 2)
#=> [1, 2]

MyClass.instance_method(:foo).parameters
#=> [[:keyreq, :bar], [:keyreq, :baz]]

      

+1


source







All Articles