J'ai le code Ruby suivant:
local_var = "Hello"
def hello
puts local_var
end
hello
J'obtiens l'erreur suivante:
local_variables.rb:4:in 'hello': undefined local variable or method 'local_var'
for main:Object (NameError) from local_variables.rb:7:in '<main>'
J'ai toujours pensé que les variables locales ne sont pas accessibles de l'extérieur du bloc, de la fonction, de la fermeture, etc.
Mais maintenant, j'ai défini une variable locale dans le fichier et j'essaie d'obtenir un accès à partir de la fonction À L'INTÉRIEUR DE le même fichier.
Quel est le problème avec ma compréhension?
Dans Ruby variables locales accessibles uniquement dans la portée où elles sont définies. Chaque fois que vous entrez/quittez une classe, un module ou une méthode, votre portée change dans Ruby.
Par exemple :
v1 = 1
class MyClass # SCOPE GATE: entering class
v2 = 2
local_variables # => ["v2"]
def my_method # SCOPE GATE: entering def
v3 = 3
local_variables # => ["v3"]
end # SCOPE GATE: leaving def
local_variables # => ["v2"]
end # SCOPE GATE: leaving class
Ces points d'entrée et de sortie sont appelés Scope Gates. Puisque vous entrez via Scope Gate via la définition de méthode, vous ne pouvez pas accéder à votre local_var
inside hello
méthode.
Vous pouvez utiliser le concept Scope Flattening pour passer votre variable à travers ces portes.
Par exemple, au lieu d'utiliser def
pour définir votre méthode, vous pouvez utiliser Module#define_method
.
local_var = "Hello"
define_method :hello do
puts local_var
end
De la même manière, vous pouvez définir vos classes via Class#New
afin que votre portée ne change pas lorsque vous passez par la définition de classe.
local_var = 'test'
MyClass = Class.new do
puts local_var #valid
end
au lieu de
class MyClass
puts local_var #invalid
end
De la même manière, vous devez utiliser Module#New
si vous voulez passer vos variables locales via les portes du module.
L'exemple est tiré de Metaprogramming Ruby