You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby中如何在Mail.deliver块内访问外层上下文self调用Wrapper实例方法

解决方案

你可以通过以下两种方式解决该问题,无需修改get_email_body为类方法:

方式1:提前计算邮件内容(更推荐)

直接在进入Mail.deliver块之前调用get_email_body生成内容,将结果存为局部变量后传入块内即可,避免在块内访问外层实例,同时也避免了循环内重复调用方法的开销。
修改后的代码如下:

class Wrapper
  def get_email_body rdv
    body = "<h1>There is an appointment available!</h1><br>"
    body += "Title: <b>#{rdv['title']}</b><br>"
    body += "Date: <b>#{rdv['start']}</b><br>"
    body + "Link: <a href='#{rdv['link']}'>"
  end

  def send_email rdv
    # 提前在Wrapper实例上下文生成邮件内容
    email_body = get_email_body(rdv)
    TARGET_EMAIL_ADDRESSES.each do|email|
      Mail.deliver do
        to email
        from 'my_email_address'
        subject 'Appointments available!'
        html_part do
          content_type 'text/html; charset=UTF-8'
          # 直接使用提前生成的内容变量
          body email_body
        end
      end
    end
  end
end

方式2:捕获外层实例引用

如果确实需要在块内动态调用Wrapper实例的方法,可以在进入Mail.deliver块之前,将外层的self(也就是Wrapper实例)存到局部变量中。Ruby的块是闭包,会保留定义时上下文的局部变量,即使块内部self被修改也不影响该变量的引用。
修改后的send_email方法如下:

def send_email rdv
  # 捕获外层Wrapper实例的引用
  wrapper_instance = self
  TARGET_EMAIL_ADDRESSES.each do|email|
    Mail.deliver do
      to email
      from 'my_email_address'
      subject 'Appointments available!'
      html_part do
        content_type 'text/html; charset=UTF-8'
        # 通过捕获的变量调用实例方法
        body wrapper_instance.get_email_body(rdv)
      end
    end
  end
end

内容的提问来源于stack exchange,提问作者Redouane Red

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 02:00:01