Изучите подход Ruby к передаче объектов в методах и присваиваниях.
Вот простой код на Ruby:
def init_options(options) options = { widget: true } end def add_default_config(options) options[:add_on] ||= true end
Не зацикливайтесь на дизайне кода. Могут быть лучшие способы выразить это, но здесь я хочу сосредоточиться на том, что происходит при выполнении следующих операторов:
options = { plugin: true } add_default_config(options) puts options # => {:plugin=>true, :add_on=>true} init_options(options) puts options # => {:plugin=>true, :add_on=>true}
Обратите внимание, что после выполнения init_options
содержимое остается прежним, даже если внутри есть инструкция, которая создаст экземпляр нового хэша.
Или взгляните на следующий код:
options = { widget: true } options.tap do |opt| opt[:widget] = false end puts options # => { :widget => false } new_options = { plugin: true } new_options.tap do |opt| opt = {} opt = { plugin: false } end puts new_options # => { :plugin => true }
Почему в этом случае new_options
не меняется после выполнения тапа?
Чтобы ответить на этот вопрос, мы должны понять, как в Ruby передаются объекты: по значению или по ссылке?
Давайте узнаем, как работает Ruby, когда речь идет о передаче объектов.
Переменная — это ссылка на объект
Чтобы понять это, я выполню ряд операторов и шаг за шагом объясню, как они работают:
options = {} puts options.object_id # => 60
Это сделает две вещи:
- Создает новый объект Hash, который в данном конкретном случае на моей машине имеет идентификатор
60
Создайте метку опции и свяжите ее с вновь созданным объектом.
Затем вызов options.object_id
вернет целое число, которое однозначно идентифицирует этот объект во время выполнения программы.
Представьте, что Ruby просто создает связь между меткой options
) и объектом, связанным с этой меткой.