2010-08-11 3 views
0

Prenez la classe suivante:Réflexion sur les paramètres de la méthode en Ruby

class Automator 
    def fill_specific_form(fields) 
    fields.each_pair do |key, value| 
     puts "Setting '#{key}' to '#{value}'" 
    end 
    end 
end 

a = Automator.new 
a.fill_specific_form :first_name => "Mads", :last_name => "Mobæk" 

# => Setting 'first_name' to 'Mads' 
# => Setting 'last_name' to 'Mobæk' 

Est-il possible de faire la même chose sans un hachage? Étant donné que tous les paramètres sont nécessaires, je veux une méthode avec la signature suivante:

fill_specific_form(first_name, last_name) 

Dans mon esprit, cela serait possible en ayant le corps de la méthode réfléchir et itérer sur ses paramètres, réalisant ainsi le même résultat.

Comment implémenteriez-vous cela? Est-ce qu'un patron/idiome pour cela existe déjà? Deux avantages évidents seraient les informations de paramètres dans les IDE et ne pas avoir à vérifier si toutes les clés de hachage sont fournies.

Ce que je veux éviter est:

puts "Setting first_name to #{first_name}" 
puts "Setting last_name to #{last_name}" 
# and so on 
+0

Dupliquer de [Ruby - affiche le nom de la variable puis sa valeur] (http://stackoverflow.com/questions/2603617/ruby-print-the-variable-name-and-then-its-value) –

+0

This est un doublon de [Existe-t-il un moyen de renvoyer un nom de paramètre de méthode dans ruby] (http://StackOverflow.Com/q/2452077/#2452322). –

Répondre

3

Si vous ne définissez pas d'autres variables locales à l'intérieur de la méthode, local_variables vous donnera une liste des noms des paramètres de la méthode (si vous ne définissez d'autres variables que vous pouvez simplement appeler local_variables première chose et rappelez-vous le résultat). Ainsi, vous pouvez faire ce que vous voulez avec local_variables + eval:

class Automator 
    def fill_specific_form(first_name, last_name) 
    local_variables.each do |var| 
     puts "Setting #{var} to #{eval var.to_s}" 
    end 
    end 
end 

Automator.new().fill_specific_form("Mads", "Mobaek") 

Soyez toutefois indiqué que ce mal pur.

Et au moins pour votre exemple

puts "Setting first_name to #{first_name}" 
puts "Setting last_name to #{last_name}" 

semble beaucoup plus sensible. Vous pouvez également faire fields = {:first_name => first_name, :last_name => last_name} au début de la méthode, puis aller avec votre code fields.each_pair.

+0

Le mal pur n'est pas destiné et pas ce que je veux. Juste curieux de savoir s'il y avait un moyen de le faire. Je vais tester vos suggestions et revenir à vous –

+0

fields = {: first_name => first_name,: last_name => last_name} est ce que je veux. Je vous remercie. –

+0

J'ai essayé avec Ruby 1.9.3, et vous devez faire # {eval var.to_s} pour le faire fonctionner, sinon vous obtenez un TypeError: impossible de convertir Symbol en String –

0

Je ne comprends pas tout à fait. Voulez-vous recevoir tous les paramètres dans un seul tableau?

def fill_specific_form *args 
    #Process args 
end 
+0

Pas tout à fait. Cela ne fait que passer les valeurs. En utilisant des noms de paramètres explicites correspondant au nom d'un élément de formulaire, je pourrais alors définir name = value. Voir la réponse de sepp2k –

0

Pour réfléchir sur les paramètres, vous pouvez utiliser Proc#parameters, Method#parameters ou UnboundMethod#parameters est une méthode (ou Proc « s):

->(m1, o1=nil, *s, m2, &b){}.parameters 
# => [[:req, :m1], [:opt, :o1], [:rest, :s], [:req, :m2], [:block, :b]] 

Cependant, dans votre cas, je ne vois pas pourquoi vous avez besoin de réflexion, depuis vous connaissez déjà les noms des paramètres de toute façon.

+0

Est-ce nouveau dans 1.9.2? Cela ne fonctionne pas pour moi en 1.8.7 ou 1.9.1. – sepp2k

+0

@ sepp2k: Oui, 'ProC# parameters' est nouveau dans 1.9.2. –

Questions connexes