2009-08-26 3 views
3

Я хочу изменить аргументы по умолчанию, переданные функции Ruby. Например, вместо того, чтобы каждый раз писатьИзменение аргументов по умолчанию Ruby

[1,2,3].do_stuff(:option => ' my option ') 

Я хочу, чтобы изменить параметры по умолчанию, так что я могу написать

[1,2,3].do_stuff 

Что является самым простым, чистым, большинство Ruby, как способ изменения параметров по умолчанию ?

ответ

2
>> [1, 2, 3].do_stuff 
=> Result I get 
>> [1, 2, 3].do_stuff :an_option => a_value 
=> Result I really want, but don't want to specify the argument 

Мне нравится использовать super для этого. Это позволяет добавить некоторые функциональные возможности методы, кроме только изменяющихся аргументов по умолчанию:

class Array 
    def do_stuff(options = {}) 
    # Verify if caller has not passed the option 
    options[:argument_i_want_to_change] = default_value_i_want unless options.has_key? :argument_i_want_to_change 
    # call super 
    super 
    end 
end 

Результат:

>> [1, 2, 3].do_stuff 
=> Result that I really want 

UPDATE: Удалено reverse_merge! зависимость. (Теперь ищем лучшие альтернативы использованию метода [] =)

0

Вы хотите найти решение для кода, который не написал сам? Есть два варианта, о которых я знаю.

код вы написали сами:

def some_method_you_wrote(options) 

становится:

def some_method_you_wrote(options = { :option1 => 'value' }) 

(ответ Swanand является слишком хорошо)

Для кода вы не писали, посмотрите на методы наложения спектров. (Rails обеспечивает то, что называется alias_method_chain для этой цели, IIRC.)

+0

Проблема с этим подходом заключается в том, что опция «option1» не устанавливается, если они передают хэш опций без набора ключей «option1». – Benjamin

1

(перемещено из оригинального вопроса)

Я полагаю, вы говорите о методе массив # do_stuff который уже существует, но вы хотите изменить его немного (в вашем случае, изменив параметр по умолчанию).

Сообщение here дает хороший способ сделать это. Он не страдает от тех же проблем, что и метод псевдонимов, поскольку нет старого «старого» метода.

Вот как вы можете использовать эту технику с вашей проблемой, например (проверено с рубином 1.9)

class Array 
    old_do_stuff = instance_method(:do_stuff) 
    define_method(:do_stuff) { |options = {}| 

    options[:option] ||= " option " 
    old_do_stuff.bind(self).call(options) 
    } 
end 

Вы также можете прочитать на UnboundMethod, если приведенный выше код в заблуждение. Обратите внимание, что old_do_stuff выходит за пределы области действия после конечного оператора, поэтому это не проблема для будущих использования Array.

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