2

I'm missing some basic Ruby variables scope knowledge here. I'm trying to send an email using Mail (this is a simplified version of my production script but it has everything to show the problem):

#!/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 '[email protected]'
        to '[email protected]'
   subject 'Some subject'
      body "here the body"
  add_file :filename => 'filename.html', :content => File.read(@final_file.path)
end

mail.deliver!

The output I get is:

/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>'

So at first the file is created and filled with some text, then the puts command prints the file's path, as expected, but for some reason, after the mail variable declaration, the @final_file variable is set to nil, I can't figure out what is happening here, it seems like a garbage collector is getting rid of that variable.

1
  • This is a scope issue.. Commented Mar 17, 2014 at 12:14

1 Answer 1

3

What you see is because the block inside Mail.new is in a different scope than @final_file, as the code calls:

  if block_given?
    instance_eval(&block)
  end

This means that the block is run from within Mail's scope. This enables you to call methods like from and to.

As far as I understand from the code, you can pass arguments to the initializer like this:

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

(this is untested, so the syntax needed might be a little different).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.