splat operator on hash for keyword arguments in ruby method definition

1k Views Asked by At

I have a class like this:

class AwesomeService
  attr_reader :a, :b

  def initialize(a: 30, b: 40)
    @a = a
    @b = b
  end
end

I am trying to do something like this:

class AwesomeService
  DEFAULTS = {
    a: 30,
    b: 40
  }

  attr_reader *DEFAULTS.keys

  def initialize(**DEFAULTS)
    @a = a
    @b = b
  end
end

so that I can keep the defaults in a separate hash.

But I am getting the error:

SyntaxError ((irb): syntax error, unexpected tCONSTANT, expecting ')')
  def initialize(**DEFAULTS)
                   ^~~~~~~~

It seems like the splat operator in the initialize is not working as I expected. But it seems to be the logical way of doing that. What am I doing wrong here?

1

There are 1 best solutions below

2
matthewd On BEST ANSWER

Yeah... that's not a thing you can do.

**foo in an argument list is how you collect a kwargs hash, so it can't also be how you inject one.

More importantly, the main point of kwargs is that they explode the hash into local variables -- that can't work if it's expanding a hash at runtime.

The closest you could get would be something like:

def initialize(**values)
  values = DEFAULTS.merge(values)
  raise "..." unless (values.keys - DEFAULTS.keys).empty?
  @a = values[:a]
  @b = values[:b]
end