【问题标题】:Rails 4 model.where returning JSON instead of hashRails 4 model.where 返回 JSON 而不是哈希
【发布时间】:2025-12-11 19:05:02
【问题描述】:

我的数据库中有contacts 的列表。我这样称呼他们:

contacts = Contact.where(loaded_at: nil, failed_at: nil)

contacts[0] 返回以下内容:

=> #<Contact id: 96, client_id: 2027, branch_id: 100, phone_type: "Mobile", unit_type: "Family", phone_number: "(123)456-7890", text_message_id: nil, loaded_at: nil, created_at: "2014-03-17 22:01:53", updated_at: "2014-03-17 22:01:53", failed_at: nil>

然后我试图在我的 Sidekiq 工作人员中循环遍历所有 contacts

  def perform()
    contacts = Contact.where(loaded_at: nil, failed_at: nil)
    contacts.each { |contact| TextSendWorker.perform_async(contact) }
  end

这会引发以下错误:

 WARN: {"retry"=>true, "queue"=>"default", "class"=>"ContactWorker", "args"=>[], "jid"=>"3d3373e14f4bfe9ae2aa2cae", "enqueued_at"=>1395093915.4475722, "error_message"=>"undefined method `key?' for #<JSON::Ext::Generator::State:0x007f40b0bd42d0>", "error_class"=>"NoMethodError", "failed_at"=>1395093915.4909346, "retry_count"=>7, "retried_at"=>1395096684.1267653}
 WARN: undefined method `key?' for #<JSON::Ext::Generator::State:0x007f40b0bd42d0>

所以,看起来我的 contacts 数组实际上返回了一个 JSON 对象数组,而不是哈希。我想我从来没有见过这个,似乎我在调用Model.where()时总是收到一个哈希。

是什么原因造成的,我怎样才能像我需要的那样在我的工作人员中循环contacts

编辑

下面的全班:

class ContactWorker
  include Sidekiq::Worker

  def perform()
    contacts = Contact.where(loaded_at: nil, failed_at: nil)
    contacts.each { |contact| TextSendWorker.perform_async(contact) }
  end
end
 

【问题讨论】:

  • perform方法在什么类下。你从另一个调用一个异步任务很奇怪。
  • 联系人也没有返回 json。是 sidekiq 尝试将您的对象转换为哈希以进行存储,以便可以异步调用 TextSendWorker #perform
  • @ahmed 感谢您的提示,您能推荐一个更好的替代方法来调用另一个异步任务吗?目前,一个 rake 任务会启动一个获取联系人列表的工作人员,然后将这些联系人发送到各个工作。我不希望我的 rake 任务运行太久。另外,我编辑了我的帖子以展示课程。它在 ContactWorker 类中。

标签: ruby-on-rails ruby json hash


【解决方案1】:

Sidekiq 序列化传递的参数以将它们存储为 redis,我认为你的序列化器有这个问题。

我建议您遵循此文档 a Best Practices 并重写代码:

class ContactWorker
  include Sidekiq::Worker

  def perform()
    contacts = Contact.where(loaded_at: nil, failed_at: nil)
    contacts.each { |contact| TextSendWorker.perform_async(contact.id) }
   end
 end

【讨论】:

  • 就是这样 - 谢谢。