2009-08-26 11 views
3

Je souhaite modifier les arguments par défaut transmis à une fonction Ruby. Par exemple, au lieu de chaque fois que l'écritureModification des arguments Ruby par défaut

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

Je veux modifier les paramètres par défaut afin que je puisse écrire

[1,2,3].do_stuff 

Quelle est la plus simple, plus propre, moyen le plus Ruby comme de changer les paramètres par défaut ?

Répondre

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 

J'aime utiliser super pour cela. Il nous permet d'ajouter des fonctionnalités à la méthode en dehors de tout changement des arguments par défaut:

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 

Résultat:

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

MISE À JOUR: Enlevé reverse_merge! dépendance. (Maintenant à la recherche d'une meilleure alternative à l'utilisation de la méthode [] =)

0

Voulez-vous une solution pour le code que vous n'avez pas écrit vous-même? Il y a deux options que je connais.

code vous écrit:

def some_method_you_wrote(options) 

devient:

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

(réponse de Swanand est bien aussi)

Pour le code que vous n'avez pas écrit, regardez dans les méthodes d'aliasing. (Rails offre quelque chose appelé alias_method_chain à cet effet, IIRC.)

+0

Le problème avec cette approche est que l'option 'option1' n'est pas définie si elle passe dans un hachage d'options sans le jeu de clés 'option1'. – Benjamin

1

(déplacé de votre question initiale)

Je suppose que vous parlez d'une méthode Tableau # do_stuff qui existe déjà, mais vous voulez modifier légèrement (dans votre cas en changeant un paramètre par défaut).

Un article here est une bonne façon de le faire. Il ne souffre pas des mêmes problèmes que la technique des alias, car il n'y a pas de "vieille" méthode restante.

Voici comment vous pouvez utiliser cette technique avec votre exemple de problème (testé avec rubis 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 

Vous pouvez également lire sur UnboundMethod si le code ci-dessus est source de confusion. Notez que old_do_stuff sort de la portée après l'instruction end, donc ce n'est pas un problème pour les futures utilisations de Array.

Questions connexes