Здесь происходит то, что аргументы не анализируются так, как вы ожидаете. В Ruby есть функция, где любые key: value
в конце списка аргументов превращаются в Hash
без необходимости помещать {}
вокруг них.
Например, если вы пишете метод:
def load(source, options = {})
end
Это можно назвать load(source)
, в этом случае options
будет {}
, или как что-то вроде load(source, foo: 5, bar: true)
, в этом случае options
будет {foo: 5, bar: true}
Другая деталь заключается в том, что необязательные параметры со значениями по умолчанию заполняются слева направо.
Почему это актуально?
Что ж, в случае JSON.load(file, proc: nil, symbolize_names: true)
proc: nil, symbolize_names: true
становится хешем {proc: nil, symbolize_names: true}
, и это затем заполняет позицию proc
в списке аргументов, оставляя параметр options
со значением по умолчанию. то есть вы на самом деле не устанавливаете symbolize_names: true
, когда вы думали, что это так.
В случае JSON.load(file, nil, symbolize_names: true)
, nil
заполняет значение параметра proc
, и symbolize_names: true
становится options
. Это объединяется с параметрами по умолчанию в библиотеке JSON для предоставления полного набора параметров, {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true, :symbolize_names=>true}
, который затем содержит конфликт, на который ссылается сообщение об ошибке.