我需要在后台标记一组消息(我正在使用delayed_job gem),因为前景需要一些时间。我已经创建了一个ActiveJob
类MarkMessagesAsReadJob
,并将user
和messages
个变量传递给了messages
所有user
{1}}。
// passing the values in the controller
@messages = @conversation.messages
MarkMessagesAsReadJob.perform_later(current_user, @messages)
在我的ActiveJob类中,我执行任务。
// MarkMessagesAsReadJob.rb
class MarkMessagesAsReadJob < ActiveJob::Base
queue_as :default
def perform(user, messages)
messages.mark_as_read! :all, :for => user
end
end
然而,当我尝试执行任务时,我收到了错误 ActiveJob :: SerializationError(不支持的参数类型:ActiveRecord :: Associations :: CollectionProxy):
我读到我们只能将支持的类型传递给ActiveJob,我认为它无法序列化CollectionProxy对象。我该如何解决/修复此问题?
PS:我考虑了
@messages.map { |message| MarkMessagesAsReadJob.perform_later(current_user, message) }
然而,我认为逐一标记它们非常昂贵。
答案 0 :(得分:6)
我认为简单的方法是将消息ID传递给perform_later()
方法,例如:
:
@messages = @conversation.messages
message_ids = @messages.pluck(:id)
MarkMessagesAsReadJob.perform_later(current_user, message_ids)
并在ActiveJob
:
def perform(user, message_ids)
messages = Message.where(id: ids)
messages.mark_as_read! :all, :for => user
end
答案 1 :(得分:3)
因为作业将在稍后执行,我认为我们应该将id作为参数而不是集合
ActiveJob需要serialize参数,如果不支持参数类型,则抛出SerializationError http://api.rubyonrails.org/classes/ActiveJob/SerializationError.html
例如:
@message_ids = @conversation.messages.pluck(:id)
# use string if array is not supported
# @message_ids = @message_ids.join(", ")
MarkMessagesAsReadJob.perform_later(current_user, @message_ids)
然后再次查询这些消息并标记
class MarkMessagesAsReadJob < ActiveJob::Base
queue_as :default
def perform(user, message_ids)
# use string if array is not supported
# message_ids = message_ids.split(",").map(&:to_i)
messages = Message.where(id: message_ids) #change this to something else
messages.mark_as_read! :all, :for => user
end
end
未经测试,希望它没问题
答案 2 :(得分:1)
对于较大的数据集,传递message_ids是不切实际的。相反,请传递SQL消息:
@messages = @conversation.messages
MarkMessagesAsReadJob.perform_later(current_user, @messages.to_sql)
然后从作业中查询它们:
class MarkMessagesAsReadJob < ActiveJob::Base
queue_as :default
def perform(user, messages_sql)
messages = Message.find_by_sql(messages_sql)
messages.mark_as_read! :all, :for => user
end
end