【问题标题】:Class methods defined as instance methods定义为实例方法的类方法
【发布时间】:2015-06-25 15:08:13
【问题描述】:

这是 Michael Hartle 书中的工作代码。这是app/mailers/user_mailer.rb 中的邮件代码,用于为用户帐户创建激活邮件:

class UserMailer < ActionMailer::Base
  def account_activation(user)
    @user = user
    mail to: user.email, subject: "Account activation"
  end
end

邮件的预览是使用test/mailers/previews/user_mailer_preview.rb中的ruby文件生成的:

class UserMailerPreview < ActionMailer::Preview
  def account_activation
    user = User.first
    user.activation_token = User.new_token
    UserMailer.account_activation(user)
  end
end

account_activation 方法在user_mailer.rb 中定义为实例方法。但它在预览生成器中用作类方法。我误解了代码还是这里发生了其他事情?

致所有有同样疑问的人

这就是 ActionMailer 的工作原理。电子邮件被定义为扩展 ActionMailer::Base 的类中的实例方法,但您可以将它们作为类方法访问。

【问题讨论】:

  • 无法复制。

标签: ruby-on-rails ruby


【解决方案1】:

ActionMailer 就是这样工作的。电子邮件被定义为扩展 ActionMailer::Base 的类中的实例方法,但您可以将它们作为类方法访问。

class MyMailer < ActionMailer::Base
  def my_email
  end
end

MyMailer.my_email
# and not MyMailer.new.my_email

这是一个快捷方式,它将实例化 ActionMailer 类的一个实例,调用相应的电子邮件方法并返回一封电子邮件消息。这是the code that handles the call

【讨论】:

    【解决方案2】:

    deliver/deliver_now/deliver_later(或任何其他交付方法)背后的魔术:

    def deliver_now
      processed_mailer.handle_exceptions do
        message.deliver
      end
    end
    

    看起来processed_mailer 是我们正在寻找的关键方法:

    def processed_mailer
      @processed_mailer ||= @mailer_class.new.tap do |mailer|
        mailer.process @action, *@args
      end
    end
    

    此方法创建邮件程序的实例,使用@action 参数(这是实例方法的名称)和@args 调用process 方法,这是传递给类方法的参数,最后它返回创建的邮件程序实例。

    这就是邮件方法被声明为实例方法但被调用为类方法的原因。

    快乐学习:)

    【讨论】:

      猜你喜欢
      • 2020-10-24
      • 1970-01-01
      • 1970-01-01
      • 2013-04-30
      • 2017-09-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-31
      • 1970-01-01
      相关资源
      最近更新 更多