Заставить объект Ruby реагировать на оператор двойного знака **

У меня есть библиотека с #execute метод вроде этого

def execute(query, **args)
  # ...
end

У меня есть класс, который генерирует данные для args (в котором много логики в зависимости от возможностей пользователя)

class Abilities
  def to_h
    { user: user } # and a lot more data
  end
end

Теперь, когда я использую #execute Я всегда должен помнить о том, чтобы использовать #to_h, что очень раздражает и приводит к ошибкам, когда кто-то его забывает:

execute(query, abilities.to_h)

Поэтому мне было интересно, если мой Abilities класс мог как-то ответить на ** (двойной знак), чтобы я мог просто передать объект:

execute(query, abilities)

Когда я пытаюсь назвать это так, выдает ошибку:

ArgumentError: wrong number of arguments (given 2, expected 1)

Итак, есть ли способ сделать мой Abilities класс вести себя как Hash? Я мог бы получить это такAbilities < Hash но тогда у меня есть вся хеш-логика, которая кажется довольно грязной.

2 ответа

Решение

Вы можете реализовать to_hash: (или определите его как псевдоним для to_h)

class MyClass
  def to_hash
    { a: 1, b: 2 }
  end
end

def foo(**kwargs)
  p kwargs: kwargs
end

foo(MyClass.new)
#=> {:kwargs=>{:a=>1, :b=>2}}

Если вы укажете API для execute таким образом, что он принимает все, что поддерживает to_h, тогда у вас есть решение:

def execute(query, args = {})
  args = args.to_h
  ...
end
Другие вопросы по тегам