2014-01-12 51 views
0

當我嘗試將內存中的對象保存到數據庫,然後使用Dalli緩存該對象時,出現奇怪的行爲。Dalli:您嘗試緩存無法序列化爲memcached的Ruby對象

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),是由隱式保存到數據庫呼叫創建。

我也發現重新加載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 

每戴維的想法,我想build而不是<<TrackedPoint以及添加accepts_nested_attributes_for :tracked_pointsInfraction,但那些都工作過。

我正在編組/串行錯誤日誌中:

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

我運行的Rails 3.2.13和2.7.0達利

編輯

參見:Cacheing an ActiveRecord Object that has_many through:

回答

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

0

我最好的猜測,只是看代碼的差異。

在前兩個示例中,您將創建帶有TrackedPoint.create的關聯對象,並立即將其保存在數據庫中。因此,通過「< <」分配關聯的工作原理是該對象有一個id。

在第三次使用TrackedPoint.new然後分配對象。這將利用嵌套創建。所以你需要在模型中使用「accep_nested_attributes_for」。 IIRC的正確方法是使用「構建」來正確實例化新對象的關聯。我猜你會看到一些奇怪的情況,當你重複它的軌道創建TrackedPoint對象,所以它不再是一個嵌套的屬性的情況下,它只是直接分配一個現有的對象的關聯。

+0

感謝您的想法,但我得到了相同的結果。我注意到,重新加載違規還允許我將對象保存到緩存中。我用更多的例子更新了我的問題。 –

+0

您可能必須爲您的課程編寫自定義_dump&_load方法。從元帥文件。 「如果您的類有特殊的序列化需求(例如,如果您想以某種特定格式序列化),或者如果它包含的對象不可序列化,則可以實現自己的序列化策略。」 – engineerDave