2013-03-28 5 views
3

Просмотр через кодовую базу Rails Я нахожу многочисленные ссылки на options.dup.Какова цель options.dup в Ruby on Rails?

def to_xml(options = {}) 
    require 'builder' unless defined?(Builder) 
    options = options.dup 
    .... 
end 

Очевидно, что options.dup дублирует хэш параметров, но почему вы хотите сделать это в этом контексте?

+1

Кажется, что ни один поиск не сделал, прежде чем задавать этот вопрос. Вы всегда должны попытаться получить ответ самостоятельно, и если вы не найдете ответа, тогда вы должны спросить о stackoverflow. – KULKING

+1

Я искал, и я не нашел ответ. Вот почему я спрашиваю здесь – Georgi

+2

Это разумный вопрос, который несправедливо отмечен из-за того, что авторы используют английский как второй язык. Отредактировано для ясности и проголосовало. Пожалуйста, постарайся быть немного более дружелюбными людьми, мы рубисты. – superluminary

ответ

7

dup клонирует объект. Когда вы передаете объект методу, все, что изменяет внутреннее состояние этого объекта, будет отражено в области вызова. Например, попробуйте этот код:

def replace_two(options) 
    options[:two] = "hi there" 
end 

options = { one: "foo", two: "bar" } 
replace_two(options) 
puts options[:two] 

Это будет печатать hi there, потому что replace_two() модифицировали содержимое хэш.

Если вы хотите, чтобы избежать изменений переданного в options, вы можете позвонить .dup на него, а затем какие-либо изменения, внесенные в клон не будут отражены в вызывающей сфере:

def replace_two(options) 
    options = options.dup 
    options[:two] = "hi there" 
end 

options = { one: "foo", two: "bar" } 
replace_two(options) 
puts options[:two] 

напечатает bar. Это общий шаблон, который следует за Principle of Least Astonishment. В Ruby методы, которые изменяют свои аргументы, обычно называются суффиксом !, чтобы предупредить пользователя о том, что они являются разрушительными/изменяющими действиями. Версия метода не dup должна была называться replace_two! для указания этого побочного эффекта.

+1

'dup' - это только мелкая копия, как указано в @ denis-bu. Он не будет клонировать вложенные внутренние объекты, а только внутренности первого уровня. –

+0

Спасибо, очень хорошо и подробно объяснили – Georgi

5

dup создает мелкую копию объекта. Это рубиновый материал. Поскольку в Ruby объекты, такие как Hash и Array, передаются по ссылке, когда вы меняете объект внутри функции, это изменяет исходный объект. Если это нежелательное поведение - вы создаете копию ... Так что код делает.

ruby-doc См

UPDATE

еще одна вещь. Поскольку объект передается по ссылке, options = options.dup присваивает options переменную ссылку на вновь созданную копию. Ссылка на исходный объект теряется внутри to_xml. Но он все еще, вероятно, упоминается в коде, который вызывает to_xml

Смежные вопросы