嗨,我有类似的事情:
class TrialRequest
attr_accessor :trial_email
def initialize(email)
@trial_email = email
puts "Trial_email: #{trial_email}"
end
def create
@email = ::Gmail.connect!(gmail_name, gmail_password) do |gmail|
email = gmail.compose do
to 'trial@domain.com'
from trial_email
subject trial_email
text_part do
content_type 'text/html; charset=UTF-8'
body 'Sign me up.'
end
end
#binding.pry
gmail.deliver!(email)
end
end
end
问题是compose块trial_email
内部未定义:
NameError: undefined local variable or method `trial_email' for #<Mail::Message:0x0000000431b830>
这是Ruby 1.9问题还是gmail gem问题?
我应该如何在compose块的范围内使这个方法“可见”?
更新 这是gmail gem的问题/特性 - ruby 1.9块已经改变但不是这么多! 除了接受的答案之外,另一种解决方法是将数据作为方法参数传递:
def create(trial_email)
...
end
答案 0 :(得分:4)
看起来像GMail问题给我。在块内,self
将是来自GMail gem的一些对象,因此您可以拥有to
,from
和类似的DSL细节。您应该能够将self.trial_email
放入局部变量中,然后访问块中的内容:
email_address = self.trial_email
@email = ::Gmail.connect!(gmail_name, gmail_password) do |gmail|
email = gmail.compose do
to 'trial@domain.com'
from email_address
subject email_address
#...
答案 1 :(得分:0)
您期望(正如您有权获得)该块应保留self的值,就像通常那样。看起来gmail gem在这里使用instance_exec
,它允许它将块的self值更改为Mail::Message
的实例(这就是为什么你可以调用to
和{{即使你没有定义这样的方法,也可以在那个块中使用1}}
虽然from
对于生成漂亮的DSL很方便,但它并非没有缺点。局部变量范围不受影响,因此您可以在块之前的本地变量中存储instance_exec
或trial_email
,然后在块内使用该局部变量
答案 2 :(得分:0)
问题是你传递给compose
方法的块后来被传递给Mail.new
,最后传递给Message.new
(如果我正确地跟踪了链),那么这个块被评估为那here:
instance_eval(&block)
由于它是在另一个对象(initialize
类的实例)的Message
方法内执行的,因此您无权访问TrialRequest
对象的属性。
你可以做同样的事情而不会有任何麻烦:
email = gmail.compose
email.to = 'trial@domain.com'
email.from = trial_email
email.subject = trial_email
email.text_part do
content_type 'text/html; charset=UTF-8'
body 'Sign me up.'
end