46 votes

Variables dans les noms de méthodes ruby

J'ai le code suivant :

for attribute in site.device_attributes
  device.attribute
end

où je voudrais que le code substitue la valeur de "attribut" au nom de la méthode.

J'ai essayé device."#{attribute}" et diverses permutations.

Est-ce complètement impossible ? Est-ce que je rate quelque chose ?

J'ai envisagé de surcharger method_missing, mais je n'arrive pas à comprendre comment cela pourrait m'aider alors que mon problème est que je dois appeler une méthode "inconnue".

83voto

Maxim Kulkin Points 844

Vous pouvez utiliser la méthode #send pour appeler la méthode de l'objet par le nom de la méthode :

object.send(:foo) # same as object.foo

Vous pouvez passer des arguments à la méthode invoquée :

object.send(:foo, 1, "bar", 1.23) # same as object.foo(1, "bar", 1.23)

Ainsi, si vous avez un nom d'attribut dans la variable "attribut", vous pouvez lire l'attribut de l'objet avec

object.send(attribute.to_sym)

et écrire la valeur de l'attribut avec

object.send("#{attribute}=".to_sym, value)

Dans la version 1.8.6 de Ruby, la méthode #send peut exécuter la méthode de n'importe quel objet indépendamment de sa visibilité (vous pouvez par exemple appeler des méthodes privées). Ceci est susceptible de changer dans les futures versions de Ruby et vous ne devriez pas vous y fier. Pour exécuter des méthodes privées, utilisez #instance_eval :

object.instance_eval {
  # code as block, can reference variables in current scope
}

# or

object.instance_eval <<-CODE
  # code as string, can generate any code text
CODE

Mise à jour

Vous pouvez utiliser public_send pour appeler des méthodes en tenant compte des règles de visibilité.

object.public_send :public_foo # ok
object.public_send :private_bar # exception

19voto

Matt Campbell Points 224

La méthode "send" devrait faire ce que vous recherchez :

object = "upcase me!"
method = "upcase"
object.send(method.to_sym) # => "UPCASE ME!"

7voto

bradheintz Points 2484

Matt et Maxim ont tous deux raison, mais ils omettent un détail qui pourrait vous aider à comprendre la syntaxe #send : En Ruby, appeler une méthode revient à envoyer un message. Softies on Rails a un une explication relativement simple de cette .

2voto

David Nehme Points 11564

Vous pouvez également faire

device.instance_eval(attribute)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X