嗨,我有类似的东西:
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
问题是在撰写块内部未定义trial_email
:
NameError: undefined local variable or method `trial_email' for #<Mail::Message:0x0000000431b830>
这是 Ruby 1.9 问题还是 gmail gem 问题?
我应该如何使此方法"可见"/在撰写块的范围内?
更新:这是 gmail gem 的一个问题/功能 - Ruby 1.9 块已经改变,但没有那么大变化!除了接受的答案之外,另一种解决方法是将数据作为方法参数传入:
def create(trial_email)
...
end
看起来像一个 GMail 问题。在方块中,self
将是来自GMail宝石的一些对象,以便您可以获得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
#...
> 你期望(正如你有权的那样(块应该像往常一样保留自我的价值。看起来 gmail gem 在这里使用了 instance_exec
,它允许它将块的 self 值更改为 Mail::Message
的实例(这就是为什么即使您没有定义此类方法,您也可以在该块中调用 to
和 from
(
虽然instance_exec
对于生成漂亮的DSL很方便,但它并非没有缺点。局部变量范围不受影响,因此您可以在块之前将trial_email
或self
存储在局部变量中,然后在块内使用该局部变量
问题是你传递给compose
方法的块后来传递给Mail.new
,最后传递给Message.new
(如果我正确跟踪链(,然后这个块在这里像这样计算:
instance_eval(&block)
由于它是在不同对象(Message
类的实例(的方法initialize
执行的,因此您无权访问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