Dalli:您正在尝试缓存无法序列化为memcached的Ruby对象

时间:2014-01-12 04:24:43

标签: ruby-on-rails memcached dalli

当我尝试将内存中的对象保存到数据库然后使用Dalli缓存该对象时,我得到了奇怪的行为。

class Infraction << ActiveRecord::Base
  has_many :infraction_locations
  has_many :tracked_points, through: :infraction_locations
end

class TrackedPoint << ActiveRecord::Base
  has_many :infraction_locations
  has_many :infractions, through: :infraction_locations
end

class  InfractionLocation << ActiveRecord::Base
  belongs_to :infraction
  belongs_to :tracked_point
  belongs_to :rule
end

这有效:

i = Infraction.create
i.tracked_points << TrackedPoint.create(location_id: 1)
i.save
Rails.cache.write "my_key", i

这也有效:

i = Infraction.new
i.tracked_points << TrackedPoint.create(location_id: 1)
i.save
Rails.cache.write "my_key", i

请注意,对象(在第二种情况下只是TrackedPoint)通过调用create隐式地保存到数据库中。

我还发现重新加载i允许我将对象写入缓存。所以这有效:

i = Infraction.new
i.tracked_points << TrackedPoint.new(location_id: 1)
i.save
i.reload
Rails.cache.write "my_key", i

这失败了:

i = Infraction.new
i.tracked_points << TrackedPoint.new(location_id: 1)
i.save
Rails.cache.write "my_key", i

但是,如果我做了一些奇怪的重复,我可以让失败的例子起作用:

i = Infraction.new
i.tracked_points << TrackedPoint.new(location_id: 1)
i.save
copy = i.dup
copy.tracked_points = i.tracked_points.to_a
Rails.cache.write "my_key", copy

在我失败的示例中,我可以在将其保存到数据库之前缓存违规行为(i),如下所示:

i = Infraction.new
i.tracked_points << TrackedPoint.new(location_id: 1)
Rails.cache.write "what", i

Per Dave的想法,我为build尝试了<<而不是TrackedPoint,并向accepts_nested_attributes_for :tracked_points添加了Infraction,但这些都没有

我在日志中收到编组/序列化程序错误:

You are trying to cache a Ruby object which cannot be serialized to memcached.

我正在运行Rails 3.2.13和Dalli 2.7.0

修改

另请参阅:Cacheing an ActiveRecord Object that has_many through:

2 个答案:

答案 0 :(得分:0)

我最好的猜测,只需查看代码差异即可。

在前两个示例中,您使用TrackedPoint.create创建关联对象,该对象会立即将其保留在数据库中。因此,通过“&lt;&lt;”分配关联因为该对象有一个id。

在第三个中,使用TrackedPoint.new,然后分配对象。这将利用嵌套创建。所以你需要在模型中使用“accepts_nested_attributes_for”。 IIRC的正确方法是使用“build”来正确实例化新对象的关联。我的猜测是你看到一些奇怪的情况,当你在rails创建TrackedPoint对象时将其复制,因此它不再是嵌套属性的情况,它只是将现有对象直接分配给关联。

答案 1 :(得分:0)

原来这是一个吱吱声问题。

有一种称为AliasTracker的东西没有被正确编组。似乎解决了这个问题的猴子补丁是:

module ActiveRecord
  module Associations
    class AliasTracker
      def marshal_dump(*)
        nil
      end

      def marshal_load(*)
        nil
      end
    end
  end
end

更多讨论和答案来自:https://github.com/activerecord-hackery/squeel/issues/232