2009-06-29 22 views
5

Esta es una pregunta para principiantes, ya que estoy tratando de aprender Ruby por mi cuenta, así que me disculpo si suena como una pregunta tonta!Ruby no se puede usar requiere

estoy leyendo a través de los ejemplos de por qué es guía (punzante) a Ruby y soy en el capítulo 4. He escrito los code_words hash en un archivo llamado wordlist.rb

abrí otro archivo y escribí la primera línea como require 'wordlist.rb' y el resto del código de la siguiente manera

#Get evil idea and swap in code 
print "Enter your ideas " 
idea = gets 
code_words.each do |real, code| 
    idea.gsub!(real, code) 
end 

#Save the gibberish to a new file 
print "File encoded, please enter a name to save the file" 
ideas_name = gets.strip 
File::open('idea-' + ideas_name + '.txt', 'w') do |f| 
    f << idea 
end 

Cuando ejecuto este código, se produce el siguiente mensaje de error:

C:/myCode/MyRubyCode/filecoder. rb: 5: undefin ed variable local o método `code_words' para main: Objeto (NameError)

uso Windows XP y Ruby versión 1.8.6 rubí

Sé que debería ser la creación de algo así como una ruta de clases, pero no está seguro dónde/cómo hacerlo!

¡Muchas gracias de antemano!

Respuesta

1

Creo que el problema podría ser que el require ejecuta el código en otro contexto, por lo que la variable de tiempo de ejecución ya no está disponible después de requerir.

Lo que podría intentar es lo que es una constante:

CodeWords = { :real => 'code' } 

que estarán disponibles en todas partes.

Here es cierto fondo en ámbitos de variable etc.

5

Mientras que el más alto nivel de todos los archivos se ejecutan en el mismo contexto, cada archivo tiene su propio contexto guión de variables locales. En otras palabras, cada archivo tiene su propio conjunto de variables locales a las que se puede acceder a través de ese archivo, pero no en otros archivos.

Por otro lado, las constantes (CodeWords), globals ($ code_words) y métodos (def code_words) serían accesibles a través de los archivos.

Algunas soluciones:

CodeWords = {:real => "code"} 

$code_words = {:real => "code"} 

def code_words 
    {:real => "code"} 
end 

Una solución OO que es definitivamente demasiado complejo para este caso:

# first file 
class CodeWords 
    DEFAULT = {:real => "code"} 

    attr_reader :words 
    def initialize(words = nil) 
    @words = words || DEFAULT 
    end 
end 

# second file 
print "Enter your ideas " 
idea = gets 
code_words = CodeWords.new 
code_words.words.each do |real, code| 
    idea.gsub!(real, code) 
end 

#Save the gibberish to a new file 
print "File encoded, please enter a name to save the file" 
ideas_name = gets.strip 
File::open('idea-' + ideas_name + '.txt', 'w') do |f| 
    f << idea 
end 
0

Una forma más sencilla sería la de utilizar la función de Marshal.dump para salvar las palabras de código .

# Save to File 
code_words = { 

'starmonkeys' => 'Phil y Pete, los cancilleres espinosas del Nuevo Reich', 'catapulta' => 'Chucky go-go', 'bomba incendiaria' => 'Living Heat-Assisted' , 'Nigeria' => "Ny y limpieza de Jerry en seco (con anillos de espuma)", 'Escribe la kabosh en' => 'Escribe la caja de cable en' }

# Serialize 
f = File.open('codewords','w') 
    Marshal.dump(code_words, f) 
f.close 

Ahora, al comienzo de su archivo que pondría esto:

# Load the Serialized Data 
code_words = Marshal.load(File.open('codewords','r')) 
0

Aquí es la manera fácil de asegurarse de que siempre se puede incluir un archivo que está en el mismo directorio que su aplicación, poner esto delante de la instrucción requerirá

$:.unshift File.dirname(__FILE__) 

$: es la variable global que representa la "ruta de clases"

1

Estaba viendo el mismo ejemplo y estaba teniendo el mismo problema. Lo que hice fue cambiar el nombre de la variable en ambos archivos de code_words a $code_words.

Esto lo convertiría en una variable global y, por lo tanto, accesible por ambos archivos, ¿verdad?

Mi pregunta es: ¿no sería esta una solución más simple que hacerlo constante y tener que escribir CodeWords = { :real => 'code' } o hay alguna razón para no hacerlo?

+0

¡Dios mío funcionó! Estaba en el mismo problema (durante un par de horas) y me preguntaba lo mismo, simplemente haciendo code_words una variable global. Déjelo en manos de alguien con algunos puntos para proporcionar la respuesta más clara, concisa y fácil de entender. Nada de esto trata de descifrar o interpretar una respuesta dada, solo un uso simple y directo de la brevedad del código. ¡Gracias! ... @ raed ¿tienes alguna señal de advertencia para otras minas terrestres de los ejercicios Poigniant de Why? – Padawan

+0

Para que funcione, también tuve que cambiar 'require' por 'require_relative'. Aquí está la diferencia entre los dos: http://stackoverflow.com/questions/3672586/what-is-the-difference-between-require-relative-and-require-in-ruby – Padawan

Cuestiones relacionadas