了解Ruby脚本中的实例变量范围

时间:2014-03-17 12:06:31

标签: ruby scope instance-variables

我在这里缺少一些基本的Ruby变量范围知识。 我尝试使用Mail发送电子邮件(这是我的生产脚本的简化版本,但它可以显示问题):

#!/usr/bin/ruby

require 'rubygems'
require 'mail'

@final_file=File.new("/usr/shared/name/ruby/file2.html","w")
@final_file.write("foo-bar")
puts @final_file.path

Mail.defaults do
  delivery_method :smtp,{ :address => 'localhost', :port => 25,:openssl_verify_mode => OpenSSL::SSL::VERIFY_NONE}
end

mail = Mail.new do
      from 'me@somehost.net'
        to 'mymail@mydomain.com'
   subject 'Some subject'
      body "here the body"
  add_file :filename => 'filename.html', :content => File.read(@final_file.path)
end

mail.deliver!

我得到的输出是:

/usr/shared/name/ruby/file2.html
email2.rb:19: warning: instance variable @final_file not initialized
email2.rb:19:in `block in <main>': undefined method `path' for nil:NilClass (NoMethodError)
        from /usr/lib64/ruby/gems/1.9.1/gems/mail-2.5.4/lib/mail/message.rb:132:in `instance_eval'
        from /usr/lib64/ruby/gems/1.9.1/gems/mail-2.5.4/lib/mail/message.rb:132:in `initialize'
        from /usr/lib64/ruby/gems/1.9.1/gems/mail-2.5.4/lib/mail/mail.rb:50:in `new'
        from /usr/lib64/ruby/gems/1.9.1/gems/mail-2.5.4/lib/mail/mail.rb:50:in `new'
        from email2.rb:14:in `<main>'

因此,首先创建文件并填充一些文本,然后puts命令按预期打印文件的路径,但出于某种原因,在邮件变量声明之后,{{ 1}}变量设置为@final_file,我无法弄清楚这里发生了什么,似乎垃圾收集器正在摆脱该变量。

1 个答案:

答案 0 :(得分:2)

您看到的是因为block内的Mail.new@final_file范围不同,因为代码calls

  if block_given?
    instance_eval(&block)
  end

这意味着该块是从 Mail范围内的运行的。这使您可以调用fromto等方法。

据我从代码中理解,您可以将参数传递给初始化程序,如下所示:

mail = Mail.new(final_path: @final_file.path) do
      from 'me@somehost.net'
        to 'mymail@mydomain.com'
   subject 'Some subject'
      body "here the body"
  add_file :filename => 'filename.html', :content => File.read(self[:final_path])
end

(这是未经测试的,因此所需的语法可能会略有不同)。