这是一个新手问题,因为我试图自己学习Ruby,如果这听起来像个愚蠢的问题,请道歉!
我正在阅读第4章中为什么(尖锐的)ruby指南的例子。我将code_words Hash键入一个名为wordlist.rb的文件
我打开另一个文件并输入第一行作为require'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'for main:Object(NameError)
我使用的是Windows XP和Ruby版本的ruby 1.8.6
我知道我应该设置类似ClassPath的东西,但不知道在哪里/怎么做!
非常感谢提前!
答案 0 :(得分:5)
虽然所有文件的顶级都在同一个上下文中执行,但每个文件都有自己的局部变量脚本上下文。换句话说,每个文件都有自己的一组局部变量,可以在整个文件中访问,但不能在其他文件中访问。
另一方面,可以跨文件访问常量(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 :(得分:1)
我认为问题可能是require在另一个上下文中执行代码,因此在require之后运行时变量不再可用。
你可以尝试使它成为一个常数:
CodeWords = { :real => 'code' }
随处可见。
Here是关于变量范围等的一些背景知识。
答案 2 :(得分:1)
我只是看着同样的例子并且遇到了同样的问题。
我所做的是将两个文件中的变量名称从code_words
更改为$code_words
。
这会使它成为一个全局变量,因此可以被两个文件访问吗?
我的问题是:这不是一个更简单的解决方案,而不是让它成为一个常数并且必须写CodeWords = { :real => 'code' }
或者是否有理由不这样做?
答案 3 :(得分:0)
更简单的方法是使用Marshal.dump功能来保存代码字。
# Save to File
code_words = {
'starmonkeys'=&gt; '菲尔和皮特,新帝国的那些多刺的大臣', 'catapult'=&gt; 'chucky go-go','firebomb'=&gt; '热辅助生活', 'Nigeria'=&gt; “Ny和Jerry的干洗(和甜甜圈)”, '把kabosh打开'=&gt; '把电缆盒放上' }
# 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'))
答案 4 :(得分:0)
这是确保您始终可以包含与您的应用位于同一目录中的文件的简单方法,将其放在require语句之前
$:.unshift File.dirname(__FILE__)
$:是表示“CLASSPATH”的全局变量