Rails 4.2:使用 deliver_later 和无表模型
Rails 4.2: using deliver_later with a tableless model
我正在尝试使用 Rails 4.2 的 deliver_later 方法设置联系表。但是,我只能让 deliver_now 工作,因为 deliver_later 正在尝试序列化我的对象并且每次都失败。
这是我的设置:
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
时得到的错误是:
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 的东西,但我认为最好事先解决这个序列化问题。
感谢任何帮助!谢谢:)
您需要先序列化对象,然后再传递给 AJ 并在邮件程序中反序列化。
为了将您的 class 与 ActiveJob
一起使用(这就是 deliver_later
委托的目的),它需要能够通过其 ID 唯一标识对象。此外,它需要在反序列化时通过 ID 找到它(不需要在邮件程序/作业中手动反序列化)。
class Message
...
include GlobalID::Identification
...
def id
...
end
def self.find(id)
...
end
end
ActiveRecord
会为您提供这些方法,但由于您没有使用它,因此您需要自己实现它。由您决定存储记录的位置,但老实说,我认为使用 ActiveRecord
和下面的 table 会更好。
一个简单的解决方案,避免必须使用 ActiveRecord 支持对象或创建不必要的 table:
除了将 Message 对象传递给 contact_form 方法之外,您还可以将消息参数传递给 contact_form 方法,然后在该方法中初始化 Message 对象。
这将解决问题而无需创建 table,因为您正在初始化延迟作业工作人员内存中的对象 space。
例如:
messages_controller.rb
MessagesController < ApplicationController
def new
@message = Message.new
end
def create
@message = Message.new(params[:message])
if @message.valid?
ContactMailer.contact_form(params[: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_params)
@message = Message.new(msg_params)
mail(:subject => msg.subject, from: msg.email)
end
end
今天遇到了类似的问题,解决方法如下
- 将无表对象转换为 JSON sting
- 将其传递给邮寄者
- 将 json 字符串转换为散列
环境
- Rails 5.0.2
messages_controller.rb
class MessagesController < ApplicationController
# ...
def create
@message = Message.new(message_params)
if @message.valid?
ContactMailer.contact_form(@message.serialize).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(message_json)
@message = JSON.parse(message_json).with_indifferent_access
mail(subject: @message[:subject], from: @message[:email])
end
end
message.rb
class Message
include ActiveModel::Model
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
# Convert an object to a JSON string
def serialize
ActiveSupport::JSON.encode(self.as_json)
end
end
希望这对任何人都有帮助。
我正在尝试使用 Rails 4.2 的 deliver_later 方法设置联系表。但是,我只能让 deliver_now 工作,因为 deliver_later 正在尝试序列化我的对象并且每次都失败。
这是我的设置:
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
时得到的错误是:
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 的东西,但我认为最好事先解决这个序列化问题。
感谢任何帮助!谢谢:)
您需要先序列化对象,然后再传递给 AJ 并在邮件程序中反序列化。
为了将您的 class 与 ActiveJob
一起使用(这就是 deliver_later
委托的目的),它需要能够通过其 ID 唯一标识对象。此外,它需要在反序列化时通过 ID 找到它(不需要在邮件程序/作业中手动反序列化)。
class Message
...
include GlobalID::Identification
...
def id
...
end
def self.find(id)
...
end
end
ActiveRecord
会为您提供这些方法,但由于您没有使用它,因此您需要自己实现它。由您决定存储记录的位置,但老实说,我认为使用 ActiveRecord
和下面的 table 会更好。
一个简单的解决方案,避免必须使用 ActiveRecord 支持对象或创建不必要的 table:
除了将 Message 对象传递给 contact_form 方法之外,您还可以将消息参数传递给 contact_form 方法,然后在该方法中初始化 Message 对象。
这将解决问题而无需创建 table,因为您正在初始化延迟作业工作人员内存中的对象 space。
例如:
messages_controller.rb
MessagesController < ApplicationController
def new
@message = Message.new
end
def create
@message = Message.new(params[:message])
if @message.valid?
ContactMailer.contact_form(params[: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_params)
@message = Message.new(msg_params)
mail(:subject => msg.subject, from: msg.email)
end
end
今天遇到了类似的问题,解决方法如下
- 将无表对象转换为 JSON sting
- 将其传递给邮寄者
- 将 json 字符串转换为散列
环境
- Rails 5.0.2
messages_controller.rb
class MessagesController < ApplicationController
# ...
def create
@message = Message.new(message_params)
if @message.valid?
ContactMailer.contact_form(@message.serialize).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(message_json)
@message = JSON.parse(message_json).with_indifferent_access
mail(subject: @message[:subject], from: @message[:email])
end
end
message.rb
class Message
include ActiveModel::Model
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
# Convert an object to a JSON string
def serialize
ActiveSupport::JSON.encode(self.as_json)
end
end
希望这对任何人都有帮助。