Rails 4.2:在无表模型中使用deliver_later [英] Rails 4.2: using deliver_later with a tableless model

查看:69
本文介绍了Rails 4.2:在无表模型中使用deliver_later的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Rails 4.2 的 Deliver_later 方法设置联系表单.但是,我只能让deliver_now 工作,因为deliver_later 试图序列化我的对象并且每次都失败.

I am trying to setup a contact form using Rails 4.2's deliver_later method. However, I can only get deliver_now to work, as deliver_later is trying to serialize my object and fails each time.

这是我的设置:

messages_controller.rb

class MessagesController < ApplicationController
  def new
    @message = Message.new
  end

  def create
    @message = Message.new(params[:message])
    if @message.valid?
      ContactMailer.contact_form(@message).deliver_later
      redirect_to root_path, notice: "Message sent! Thank you for contacting us."
    else
      render :new
    end
  end
end

contact_mailer.rb

class ContactMailer < ApplicationMailer
  default :to => Rails.application.secrets['email']

  def contact_form(msg)
    @message = msg
    mail(:subject => msg.subject, from: msg.email)
  end
end

message.rb

class Message
    include ActiveModel::Model
    include ActiveModel::Conversion

    ## Not sure if this is needed ##
    include ActiveModel::Serialization

    extend ActiveModel::Naming

    attr_accessor :name, :subject, :email, :body

    validates_presence_of :email, :body
    validates_format_of :email, with: /\A([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})\z/i
    validates_length_of :body, :maximum => 1000

    def initialize(attributes = {})
      attributes.each { |name, value| send("#{name}=", value) }
    end

    ## Not sure if this is needed ##
    def attribtues
      {'name' => nil, 'subject' => nil, 'email' => nil, 'body' => nil}
    end
end

我在调用 ContactMailer.contact_form(@message).deliver_later 时得到的错误是:

The error I get when calling ContactMailer.contact_form(@message).deliver_later is:

ActiveJob::SerializationError in MessagesController#create 

Unsupported argument type: Message
Extracted source (around line #10): 
if @message.valid?
  ContactMailer.contact_form(@message).deliver_later
  redirect_to root_path, notice: "Message sent! Thank you for contacting us."
else
  render :new

理想情况下,我希望这是一个后台进程.我很快就会添加类似 Sidekiq 的东西,但我认为最好事先解决这个序列化问题.

Ideally I'd like this to be a background process. I will be adding something like Sidekiq soon but I think it's best I get this serialization problem fixed beforehand.

感谢任何帮助!谢谢:)

Any help is appreciated! Thanks :)

推荐答案

为了将您的类与 ActiveJob(这就是 deliver_later 委托给的)一起使用,它需要能够通过其 ID 唯一标识对象.另外,后面反序列化时需要通过ID找到它(在mailer/job中不需要手动反序列化).

In order to use your class with ActiveJob (that's what deliver_later delegates to), it needs to be able to uniquely identify the object by its ID. Further, it needs to find it later by the ID when deserializing (no manual deserialize is necessary in the mailer / job).

class Message
  ...
  include GlobalID::Identification
  ...

  def id
    ...
  end

  def self.find(id)
    ...
  end
end

ActiveRecord 将为您提供这些方法,但由于您没有使用它,您需要自己实现它.由您决定要将记录存储在哪里,但老实说,我认为使用 ActiveRecord 和下面的表格会更好.

ActiveRecord would provide you with these methods but since you're not using it, you need to implement it yourself. It's up to you to decide where you want to store the record but honestly I think you'd be better off by using ActiveRecord and the table underneath.

这篇关于Rails 4.2:在无表模型中使用deliver_later的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆