Reputation: 5735
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.
Upvotes: 2
Views: 423
Reputation: 37409
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).
Upvotes: 3