Обработка метода с необязательным аргументом, за которым следует список ключевых аргументов
Я хочу передать необязательный аргумент (любой тип данных, даже хэш), за которым следует список ключевых аргументов (которые могут быть пустыми) в метод.
Вот что я получил:
def my_method(subject = nil, **options)
[subject, options]
end
Вывод метода является ожидаемым в следующих случаях:
ничего такого
my_method() # => [nil, {}]
предмет
my_method('foo') # => ["foo", {}]
буквальный предмет с опциями
my_method('foo', bar: 'bar') # => ["foo", {:bar=>"bar"}]
Hash
как предмет с опциямиmy_method({foo: 'foo'}, bar: 'bar') # => [{:foo=>"foo"}, {:bar=>"bar"}]
без темы, только варианты
my_method(bar: 'bar') # => [nil, {:bar=>"bar"}]
При прохождении Hash
как предмет и без вариантов, желаемый результат:
my_method({foo: 'foo'})
# => [{:foo=>"foo"}, {}]
Но я получаю следующее; Я не понимаю правильный предмет:
my_method({foo: 'foo'})
# => [nil, {:foo=>"foo"}]
Является my_method(foo: 'foo')
эквивалентно my_method({foo: 'foo'})
? Любые идеи о том, как я могу получить желаемый результат?
3 ответа
Видите, у вас есть **options
в качестве аргумента, который не имеет никакого значения по умолчанию, а первый аргумент имеет значение по умолчанию. Так что поймите следующий случай с одним аргументом,
Всякий раз, когда передается один аргумент, его пытаются присвоить второму аргументу (так как первый содержит значение по умолчанию nil), и если он терпит неудачу из-за несоответствия типов, он назначается первому аргументу. Вот как my_method(4)
работает.
Теперь предположим, что у вас есть один аргумент, переданный в виде хэша, который соответствует назначению 2-му аргументу, тогда, конечно, он будет назначен второму аргументу, а первый установлен по умолчанию nil.
Если вы хотите, чтобы это работало, то вы можете сделать следующее,
> my_method({sd: 4}, {})
=> [{:sd=>4}, {}]
Или вы можете указать имя аргумента при передаче,
> my_method(subject: {sd: 4})
=> [{:sd=>4}, {}]
Насколько я знаю, это ограничение того, как Руби передает аргументы. Это не может сказать разницу между my_method({foo: 'foo'})
а также my_method(foo: 'foo')
Почему бы не взломать это с этим?
if subject.is_a?(Hash) && options.empty?
subject, options = nil, subject
end
Это предполагает, что subject
не должно быть хешем.
Возможно, не самый лучший ответ, но вы можете попробовать с аргументом ключевого слова:
def my_method(subject: nil, **options)
[ subject, options ]
end
затем
my_method(subject: {foo: 'foo'})
=> [{:foo=>"foo"}, {}]
Альтернатива:
Ты можешь использовать
my_method({foo: 'foo'}, {})