web-dev-qa-db-fra.com

Ruby la variable locale n'est pas définie

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?

37
Sergii Shevchyk

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

55
emre nevayeshirazi