Mail bloğu neden değişkemi göremiyor?

Ben ruby için yeni ve basit bir Sinatra app 'posta' gem kullanarak bu durumda neden bir hata alıyorum merak ediyorum:

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

Ancak bu iyi çalışır:

post "/email/send" do

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

  erb :email_sent

end

Bunun blok kapsamı ve bunun yanlış anlaşılmasıyla ilgili bir şey olduğundan şüpheleniyorum.

8
Sorununuzun örnek varlıkla olduğundan ve params [: email] ile olmadığından emin misiniz? Çıkarmayı denediniz mi? Yine de, yerel bir değişken burada yeterli olmalıdır, çünkü blok zaten bir kapanıştır.
katma yazar Michael Kohl, kaynak

3 cevap

Julik'in dediği gibi, Mail # delivery , bloğunu çalıştırırken #instance_exec kullanarak self kodunu değiştirir. yöntemini çağırmak için #to ve #from komutlarını çağırmayın).

Burada gerçekten yapabileceğiniz şey, blokların kapanmalar olduğu gerçeğini kullanmaktır. Bunun anlamı, etrafındaki tüm yerel değişkenleri "hatırlar".

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

Yine, kısaca:

  • 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.
14
katma
Yani benim hatam bir örnek değişken kullanıyor muydu? Bir örnek değişkeni kullandım çünkü bu veri ERB şablonunda mevcut olmak istedim ve - yanılmıyorsam - bunun bir örnek var olması gerektiği anlamına geliyor. Yerel bir değişkeni ilan ederek ya da Teneke Adam'ın önerdiği yaklaşımlardan birini kullanarak çalışabilirim. Teşekkürler, şimdiye kadar Ruby'yi sevmek, ama çok şey öğrenmek :)
katma yazar Ciaran Archer, kaynak
Ve küçük bir ekleme: Bu davranış Ruby'nin bir sürümüne bağlı değildir. Yani soru başlığı "Ruby 1.9" kelimeleri kaldırmak istiyorum, bu kafa karıştırıcı olabilir.
katma yazar Daniel Vartanov, kaynak

Mail için dokümanları okuyacaksanız Ayrıca çalışacak güzel bir alternatif çözüm bulacaksınız. Kullanmak yerine:

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

Mail'in new() yöntemini parametrelerden geçirerek kullanabilir ve bloğu yoksayabilirsiniz:

Mail.new(
  to:      @recipient,
  from:    '[email protected]',
  subject: 'testing sendmail',
  body:    'testing sendmail'
).deliver!

veya alternatif karma eleman tanımları:

Mail.new(
  :to      => @recipient,
  :from    => '[email protected]',
  :subject => 'testing sendmail',
  :body    => 'testing sendmail'
).deliver!

Gözetlemek, ya da irb gördüğünüz:

pry(main)> Mail.new(
pry(main)* to: '[email protected]',
pry(main)* from: '[email protected]' << `hostname`.strip,
pry(main)* subject: 'test mail gem',
pry(main)* body: 'this is only a test'
pry(main)* ).deliver!
=> #, , , <[email protected]>>, , , , >

yeni yönteminin çeşitli varyasyonları vardır. kullanabilirsiniz. Bu, ayrıca dokümanlar ve daha iyi çalışabilir:

Bir yan not olarak, doğrudan bir Mail :: Message nesnesi oluşturarak ve sonra dize, sembol veya doğrudan yöntem çağrıları yoluyla değerleri ileterek yeni bir e-posta da oluşturabilirsiniz. Daha fazla bilgi için Mail :: Message bölümüne bakın.

 mail = Mail.new
 mail.to = '[email protected]'
 mail[:from] = '[email protected]'
 mail['subject'] = 'This is an email'
 mail.body = 'This is the body'

ardından mail.deliver! .

Ayrıca, önceki örnekte, mesaj zarfındaki çeşitli başlıklara erişmek için birden fazla yol olduğunu unutmayın. İyi düşünülmüş gibi gözüken ve güzel bir şekilde ruby yolunu izleyen esnek bir mücevher.

8
katma
Benim için bu araştırmayı yaptığınız için teşekkürler :) Ben RubyGems olanlara bakmak yerine GitHub dokümanlarına çok yakından bakıyordum. Ders orada öğrenildi. Tekrar teşekkürler.
katma yazar Ciaran Archer, kaynak

Posta geminin, kaputun altında instance_exec kullanması nedeniyle olduğunu düşünüyorum. instance_exec , çağrıldığından değil çağrıldığı nesneden örnek değişkenleri kullanır. Yapacağım şey, Posta gemisinde örnek hileleri kullanmayan, ancak bloğa açık bir yapılandırma nesnesini geçiren ve oradan devam eden bir yöntem bulmak. Birkaç gri tüyü ayırır.

3
katma