访问Rails 4.1邮件程序预览中的请求参数

时间:2015-03-18 18:08:32

标签: ruby-on-rails ruby actionmailer

当我以前使用MailView gem来预览ActionMailer个电子邮件时,我会访问@rack_env以在不同条件下预览我的电子邮件,例如交付给特定用户或特定区域,或具有特定输入。使用新的(ish)ActionMailer::Preview,实例变量未被设置,params不存在。有谁知道如何使用/rails/mailers/:mailer/:action访问GET参数ActionMailer::Preview

理想情况下,我希望能够请求/rails/mailers/my_mailer/mymail?user_id=123并像

一样使用它
class MyMailerPreview < ActionMailer::Preview
  def mymail
    MyMailer.mymail(User.find(params[:user_id]))
  end
end

3 个答案:

答案 0 :(得分:0)

ActionMailer无权访问控制器参数,因此请将所需的参数作为参数传递:

class MyMailerPreview < ActionMailer::Preview
  def mymail(user_id)
    MyMailer.mymail(User.find(user_id))
  end
end

然后在你的控制器中:

MyMailerPreview.mymail(params[:user_id]).deliver

答案 1 :(得分:0)

我想出了一个简单的解决方案,并用blog post on extending ActionMailer详细说明。这是我发现的最简单的解决方案,我唯一关心的是它如何影响其他控制器的性能。

# config/initializers/mailer_injection.rb

# This allows `request` to be accessed from ActionMailer Previews
# And @request to be accessed from rendered view templates
# Easy to inject any other variables like current_user here as well

module MailerInjection
  def inject(hash)
    hash.keys.each do |key|
      define_method key.to_sym do
        eval " @#{key} = hash[key] "
      end
    end
  end
end

class ActionMailer::Preview
  extend MailerInjection
end

class ActionMailer::Base
  extend MailerInjection
end

class ActionController::Base
  before_filter :inject_request

  def inject_request
    ActionMailer::Preview.inject({ request: request })
    ActionMailer::Base.inject({ request: request })
  end
end

答案 2 :(得分:0)

这是我用于特定参数的解决方案(在我的情况下加载特定订单),您可以修改它以使其更通用并适用于任何或所有参数

它在XXXMailerPreview类中使用了一个类变量,如果你在dev中运行它应该不是问题。这是必需的,因为至少在Rails 5中,预览显示在IFrame中,并且添加到预览URL的url参数不会传递到IFrame网址。

具体来说,此示例代码适用于Spree中的Abandoned Cart电子邮件,但它也可用于任何订单特定的电子邮件预览

预览http://localhost:3000/rails/mailers/abandonded_checkout_mailer

上的所有电子邮件

mailer_controller_decorator.rb中,你可以在加载Rails之后加载任何你想要的东西

module MailerPreviewOrderNumber
  def set_order_number(order_number)
    @order_number = order_number
  end

  def get_order_number
    @order_number
  end

  def order_for_preview
    order_number = get_order_number
    order = Spree::Order.find_by(:number => order_number) if order_number.present?
    order = yield if order.blank?
    order
  end

end

Rails::MailersController.class_eval do
  before_action :save_order_number, only: [:preview]

  def save_order_number
    if @preview.present? && @preview.respond_to?(:set_order_number)
      @preview.set_order_number(params[:order]) if params[:order].present?
    end
  end
end

在您的XXXMailerPreview文件中

class AbandondedCheckoutMailerPreview < ActionMailer::Preview
  extend MailerPreviewOrderNumber

  def abandoned_checkout_email
    if Rails.env.development?
      order = self.class.order_for_preview do
        Spree::Order.order(updated_at: :desc).last
      end
      AbandonedCheckoutMailer.abandoned_checkout_email(order)
    end
  end
end

传递给order_for_preview的块用于第一次没有为预览URL提供订单参数的情况