【问题标题】:Rails deliver_later getting Unsupported Argument TypeRails deliver_later 获取不支持的参数类型
【发布时间】:2023-01-19 23:09:48
【问题描述】:

我已将我的 Rails 应用程序中的邮件传递更改为实现 deliver_later 而不是 deliver_now,并且遇到来自 ActiveJob 的错误消息。

旧机制是:

mail_collection.each &:deliver_now

新机制是:

mail_collection.each do |m|
  m.deliver_later(wait_until: specified_time)
end

现在,当运行我的测试时,带有 deliver_later 方法的行抛出错误:

Minitest::UnexpectedError: ActiveJob::SerializationError: 不支持的参数类型:地址

如果我将 deliver_later 更改为 deliver_now 并删除选项,问题就会消失。我已经检查了对象并验证它们是邮件消息,还通过调用 m.method(:deliver_later) 验证了它正在使用:

<方法:ActionMailer::MessageDelivery#deliver_later(options=...) /usr/local/bundle/gems/actionmailer-6.1.7/lib/action_mailer/message_delivery.rb:98>

我已将 specified_time 替换为 Time.now 以确保这不是根本原因,并且我遇到了同样的错误。

我已经将 Sidekiq 更新到 7.0,因为我看到一些关于早期版本 Sidekiq 的类似问题的讨论,但没有爱。

任何关于在哪里寻找解决方案的建议将不胜感激。

【问题讨论】:

    标签: ruby-on-rails testing actionmailer


    【解决方案1】:

    使用 deliver_later 方法时,它将序列化您传递给 m 的参数,稍后这些参数将被反序列化。

    看起来你正在传递一个自定义的 Address 对象作为参数,而 ActiveJob 并不真正知道如何序列化/反序列化这个对象。

    有两种可能的解决方案:

    1. 您不传递自定义 Address 对象,即只传递具有受支持类型的属性。 在这里你可以找到支持的参数类型列表https://api.rubyonrails.org/classes/ActiveJob/SerializationError.html
    2. 您为 Address 编写了自定义序列化程序,这里有一篇博文对其进行了更详细的解释 https://blog.saeloun.com/2019/09/11/rails-6-custom-serializers-for-activejob-arguments.html

    【讨论】:

    • 非常感谢您的回答。最初,我认为这是不正确的,因为 to/from 只是被分配了字符串。但是,仔细观察后,我发现这些字符串正在更改为 Address 对象。这就提出了一个问题:如果在 Rails 4.x 中引入了 deliver_later 并且在 Rails 6 中引入了自定义序列化程序,那么 deliver later 如何在 Rails 6 之前起作用?
    • 我相信在 Rails 4.x 中,您必须自己序列化一个 Address 对象,然后将序列化的对象作为参数传递。否则将抛出 ActiveJob::SerializationError
    • 对于那些慷慨的人,我有一个关于实现序列化程序的后续问题:stackoverflow.com/questions/74853063/…
    【解决方案2】:

    ************* 最后更新 *************

    对于它的价值,我从来没有能够让序列化器工作,这也是因为那不是根本问题。

    我正在执行的代码类似于:

    create_emails.each do |m|
      m.deliver_later(wait_until: next_time_slot)
    end
    

    真正的问题是在 create_emails 方法中,调用的方法的参数不在 ActiveJob 的可序列化对象列表中。让我误入歧途的是我发送的电子邮件有一个地址参数,但是create_emails 下的方法之一也有。

    所以,我认为问题出在电子邮件的发送上,而实际上是在电子邮件的创建上,这告诉我发送电子邮件的块被传递和执行而不是电子邮件本身,是真的一点也不直观。我想我需要深入研究源代码才能完全理解发生了什么。

    一旦我将create_emails 下的所有方法都更改为具有可以由 ActiveJob 处理的参数,问题就解决了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-11
      相关资源
      最近更新 更多