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

オブジェクト (2 番目のケースでは のみ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 のアイデアに従って、 for のbuild代わりにを追加するだけでなく、toを追加しようとしましたが、どちらも機能しませんでした。<<TrackedPointaccepts_nested_attributes_for :tracked_pointsInfraction

ログにマーシャリング/シリアライザー エラーが記録されています。

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

コードの違いを見るだけで、私の最善の推測です。

最初の 2 つの例では、関連付けられたオブジェクトを TrackedPoint.create で作成しています。これにより、オブジェクトはデータベースにすぐに永続化されます。したがって、「<<」による関連付けの割り当ては、そのオブジェクトの ID があるため機能します。

3 番目では、TrackedPoint.new を使用してから、オブジェクトを割り当てます。これは、ネストされた作成を活用します。したがって、モデルには「accepts_nested_attributes_for」が必要です。IIRC の適切な方法は、「ビルド」を使用して、新しいオブジェクトの関連付けを適切にインスタンス化することです。私の推測では、レールが TrackedPoint オブジェクトを作成している場所を複製すると、奇妙なケースが発生するので、ネストされた属性のケースではなく、既存のオブジェクトを関連付けに直接割り当てるだけです。

于 2014-01-12T07:42:00.647 に答える
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

于 2014-02-24T14:11:01.757 に答える