加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在Ruby中使用块的顺序是什么

发布时间:2020-12-17 03:18:15 所属栏目:百科 来源:网络整理
导读:我正在创建一个gem来支持命令行中的一些邮件.我用了一些宝石. 我正在使用 Mail Gem.正如你在邮件描述中看到的那样,gem就是这样的. mail = Mail.new do from 'mikel@test.lindsaar.net' to 'you@test.lindsaar.net' subject 'This is a test email' body File
我正在创建一个gem来支持命令行中的一些邮件.我用了一些宝石.
我正在使用 Mail Gem.正如你在邮件描述中看到的那样,gem就是这样的.

mail = Mail.new do
  from    'mikel@test.lindsaar.net'
  to      'you@test.lindsaar.net'
  subject 'This is a test email'
  body    File.read('body.txt')
end

在块中,我从Mail类(from,to,subject,body)调用方法.这是有道理的,所以我在我自己的邮件程序类中构建它

def initialize(mail_settings,working_hours)
  @mail_settings = mail_settings
  @working_hours = working_hours
  @mailer = Mail.new do
    to mail_settings[:to]
    from mail_settings[:from]
    subject mail_settings[:subject]
    body "Start #{working_hours[:start]} n
          Ende #{working_hours[:end]}n
          Pause #{working_hours[:pause]}"
  end
end

这看起来很直接.只需调用块并填写我通过构造函数获取的值.现在是我的问题.

我试图把邮件的主体结构分成一个单独的方法.但是我不能在gem的Mail构造函数中使用它.

module BossMailer
  class Mailer
  def initialize(mail_settings,working_hours)
    @mail_settings = mail_settings
    @working_hours = working_hours
    @mailer = Mail.new do
      to mail_settings[:to]
      from mail_settings[:from]
      subject mail_settings[:subject]
      body mail_body
    end
  end

  def mail
    @mailer.delivery_method :smtp,address: "localhost",port: 1025
    @mailer.deliver
  end

  def mail_body
    "Start #{working_hours[:start]} n
    Ende #{working_hours[:end]}n
    Pause #{working_hours[:pause]}"
  end
end

结束

此错误出现在此代码中.

enter image description here

这意味着我不能在这个块中使用我的类方法或类变量(以@a开头).

问题

块中执行的顺序是什么?如果我设置我的变量@mail_settings,我不能在块中使用它. Ruby是否在Mail类中搜索@mail_settings,我在哪里给出块?为什么我可以通过块使用BossMailer :: Mailer构造函数中的给定参数,并且不会出现错误?

如果我使用和变量将内容解析为块,为什么这会起作用? (body_content = mail_body)有效!

def initialize(mail_settings,working_hours)
  @mail_settings = mail_settings
  @working_hours = working_hours
  body_content = mail_body
  @mailer = Mail.new do
    to mail_settings[:to]
    from mail_settings[:from]
    subject mail_settings[:subject]
    body body_content
  end
end

解决方法

这完全取决于背景.

mail = Mail.new do
  from    'mikel@test.lindsaar.net'
  to      'you@test.lindsaar.net'
  subject 'This is a test email'
  body    File.read('body.txt')
end

from,to methods(和其余)是Mail::Message实例上的方法.为了能够以这种漂亮的DSL方式调用它们,传递给构造函数的块是instance_eval’ed.

这意味着在这个块内部,self不再是你的邮件程序,而是邮件消息.因此,您的邮件程序方法无法访问.

而不是instance_eval,他们可能只有yield或block.call,但这不会使DSL成为可能.

至于为什么局部变量有效:这是因为ruby块是词法范围的闭包(意思是,它们保留了它们声明的局部上下文.如果有一个局部变量可以从块的定义中看到它,它会记住变量及其调用块时的值)

替代方法

不要使用块形式.使用此:https://github.com/mikel/mail/blob/0f9393bb3ef1344aa76d6dac28db3a4934c65087/lib/mail/message.rb#L92-L96

mail = Mail.new
mail['from'] = 'mikel@test.lindsaar.net'
mail[:to]    = 'you@test.lindsaar.net'
mail.subject 'This is a test email'
mail.body    = 'This is a body'

尝试评论/取消注释某些行.

class Mail
  def initialize(&block)
    # block.call(self) # breaks DSL
    instance_eval(&block) # disconnects methods of mailer
  end

  def to(email)
    puts "sending to #{email}"
  end

end

class Mailer
  def admin_mail
    # get_recipient = 'vasya@example.com'
    Mail.new do
      to get_recipient
    end
  end

  def get_recipient
    'sergio@example.com'
  end
end


Mailer.new.admin_mail

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读