Рубин не может использовать требуют - PullRequest
5 голосов
/ 30 июня 2009

Это вопрос новичка, так как я пытаюсь самостоятельно изучить Ruby, поэтому извиняюсь, если это звучит глупо!

Я читаю примеры того, почему (острое) руководство по ruby ​​и я в главе 4. Я напечатал хэш code_words в файл с именем wordlist.rb

Я открыл другой файл и набрал первую строку, как требуется 'wordlist.rb', а остальную часть кода, как показано ниже

#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

Когда я выполняю этот код, происходит сбой со следующим сообщением об ошибке:

C: /MyCode/MyRubyCode/filecoder.rb: 5: неопределенная локальная переменная или метод `code_words 'для main: Object (NameError)

Я использую Windows XP и Ruby версии ruby ​​1.8.6

Я знаю, что должен установить что-то вроде ClassPath, но не уверен, где / как это сделать!

Большое спасибо заранее!

Ответы [ 5 ]

5 голосов
/ 30 июня 2009

Хотя верхний уровень всех файлов выполняется в одном и том же контексте, каждый файл имеет собственный контекст сценария для локальных переменных. Другими словами, каждый файл имеет свой собственный набор локальных переменных, к которым можно обращаться по всему файлу, но не в других файлах.

С другой стороны, константы (CodeWords), глобальные переменные ($ code_words) и методы (def code_words) будут доступны для всех файлов.

Некоторые решения:

CodeWords = {:real => "code"}

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

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

OO-решение, которое определенно слишком сложно для этого случая:

# 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
1 голос
/ 16 января 2013

Я просто смотрел на тот же пример и у меня была та же проблема. Я изменил имя переменной в обоих файлах с code_words на $code_words.

Это сделало бы ее глобальной переменной и, следовательно, доступной для обоих файлов, верно?

У меня вопрос: не будет ли это более простым решением, чем сделать его константой и написать CodeWords = { :real => 'code' }, или есть причина не делать этого?

1 голос
/ 30 июня 2009

Я думаю, что проблема может быть в том, что require выполняет код в другом контексте, поэтому переменная времени выполнения больше не доступна после require.

То, что вы можете попробовать сделать его постоянным:

CodeWords = { :real => 'code' }

Это будет доступно везде.

Здесь - некоторый фон для переменных областей и т. Д.

0 голосов
/ 04 июля 2009

Вот простой способ убедиться, что вы всегда можете включить файл, который находится в том же каталоге, что и ваше приложение, поместите его перед оператором require

$:.unshift File.dirname(__FILE__)

$: глобальная переменная, представляющая "CLASSPATH"

0 голосов
/ 04 июля 2009

Более простой способ - использовать функцию Marshal.dump для сохранения кодовых слов.

# Save to File
code_words = {

'starmonkeys' => 'Фил и Пит, эти колючие канцлеры Нового Рейха', 'catapult' => 'chucky go-go', 'firebomb' => 'Жаркая помощь', 'Nigeria' => "Химчистка Най и Джерри (с пончиками)", 'Надень кабош' => 'Надень кабельную коробку' }

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

Теперь в начале вашего файла вы бы поместили это:

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