Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't the Mail block see my variable?

Tags:

ruby

sinatra

I'm new to Ruby and wondering why I am getting an error in this situation using the 'mail' gem in a simple Sinatra app:

post "/email/send" do

  @recipient = params[:email]

  Mail.deliver do 
    to @recipient # throws error as this is undefined
    from '[email protected]'
    subject 'testing sendmail'
    body 'testing sendmail'
  end

  erb :email_sent

end

This however works fine:

post "/email/send" do

  Mail.deliver do 
    to '[email protected]'
    from '[email protected]'
    subject 'testing sendmail'
    body 'testing sendmail'
  end

  erb :email_sent

end

I suspect this is something to do with block scope and my misunderstanding of it.

like image 885
Ciaran Archer Avatar asked Oct 28 '11 11:10

Ciaran Archer


1 Answers

As Julik says, Mail#delivery executes your block using #instance_exec, which simply changes self while running a block (you wouldn't be able to call methods #to and #from inside the block otherwise).

What you really can do here is to use a fact that blocks are closures. Which means that it "remembers" all the local variables around it.

recipient = params[:email]
Mail.deliver do 
    to recipient # 'recipient' is a local variable, not a method, not an instance variable
...
end

Again, briefly:

  • instance variables and method calls depend on self
  • #instance_exec changes the self;
  • local variables don't depend on self and are remembered by blocks because blocks are closures.
like image 135
Daniel Vartanov Avatar answered Sep 22 '22 04:09

Daniel Vartanov