0

当我尝试将内存中的对象保存到数据库中,然后用 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

根据 Dave 的想法,我尝试build代替<<forTrackedPoint以及添加 a accepts_nested_attributes_for :tracked_pointsto Infraction,但这些都不起作用。

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

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

我正在运行 Rails 3.2.13 和 Dalli 2.7.0

编辑

另请参阅:通过以下方式缓存 has_many 的 ActiveRecord 对象:

4

2 回答 2

0

我最好的猜测,只是通过查看代码差异。

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

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

于 2014-01-12T07:42:00.647 回答
0

原来是squeel的问题。

有一种称为 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

于 2014-02-24T14:11:01.757 回答