3.1.0.rc4(Ruby 1.9.2p180(2011-02-18リビジョン30909)[x86_64-darwin10])のRails.cacheメソッドで問題が発生しました。コードは、2.3.12(Ruby 1.8.7(2011-02-18パッチレベル334)[i686-linux]、MBARI 0x8770、Ruby Enterprise Edition 2011.03))の同じアプリケーション内で正常に動作します。しかし、アップグレード後にエラーを返し始めました。まだ理由がわかりません。
複数のスコープを持つオブジェクトをキャッシュしようとすると、エラーが発生するようです。
また、スコープの数に関係なく、ラムダを使用するスコープは失敗します。
私はこれらのパターンからの失敗をヒットしました:
Rails.cache.fetch("keyname", :expires_in => 1.minute) do
Model.scope_with_lambda
end
Rails.cache.fetch("keyname", :expires_in => 1.minute) do
Model.scope.scope
end
これは私が受け取るエラーです:
TypeError: can't dump hash with default proc
from /project/shared/bundled_gems/Ruby/1.9.1/gems/activesupport-3.1.0.rc4/lib/active_support/cache.rb:627:in `dump'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/activesupport-3.1.0.rc4/lib/active_support/cache.rb:627:in `should_compress?'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/activesupport-3.1.0.rc4/lib/active_support/cache.rb:559:in `initialize'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/activesupport-3.1.0.rc4/lib/active_support/cache.rb:363:in `new'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/activesupport-3.1.0.rc4/lib/active_support/cache.rb:363:in `block in write'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/activesupport-3.1.0.rc4/lib/active_support/cache.rb:520:in `instrument'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/activesupport-3.1.0.rc4/lib/active_support/cache.rb:362:in `write'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/activesupport-3.1.0.rc4/lib/active_support/cache.rb:299:in `fetch'
from (irb):62
from /project/shared/bundled_gems/Ruby/1.9.1/gems/railties-3.1.0.rc4/lib/Rails/commands/console.rb:45:in `start'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/railties-3.1.0.rc4/lib/Rails/commands/console.rb:8:in `start'
from /project/shared/bundled_gems/Ruby/1.9.1/gems/railties-3.1.0.rc4/lib/Rails/commands.rb:40:in `<top (required)>'
from script/Rails:6:in `require'
from script/Rails:6:in `<main>'
代替として:raw => trueオプションを使用してみましたが、Rails.cache.fetchブロックがオブジェクトをキャッシュしようとしているため、機能しません。
助言がありますか?前もって感謝します!
Mu-is-too-shortの優れた分析に感謝します。これでモデルをシリアル化することができました:
def marshal_dump
{}.merge(attributes)
end
def marshal_load stuff
send :initialize, stuff, :without_protection => true
end
また、AS
を使用した直接SQL結合クエリによって設定された「仮想属性」もいくつかあります。 SELECT DISTINCT posts.*, name from authors AS author_name FROM posts INNER JOIN authors ON author.post_id = posts.id WHERE posts.id = 123
。これらが機能するためには、それぞれにattr_accessor
を宣言し、次のようにそれらをダンプ/ロードする必要があります。
VIRTUAL_ATTRIBUTES = [:author_name]
attr_accessor *VIRTUAL_ATTRIBUTES
def marshal_dump
virtual_attributes = Hash[VIRTUAL_ATTRIBUTES.map {|col| [col, self.send(col)] }]
{}.with_indifferent_access.merge(attributes).merge(virtual_attributes)
end
def marshal_load stuff
stuff = stuff.with_indifferent_access
send :initialize, stuff, :without_protection => true
VIRTUAL_ATTRIBUTES.each do |attribute|
self.send("#{attribute}=", stuff[attribute])
end
end
Rails 3.2.18
スコープを使用してActiveRecord::Relation
オブジェクトを作成したことに気付きました。その後、簡単なModel.find
を実行すると効果があることに気付きました。私はそれがActiveRecord::Relation
オブジェクトを好きではないのではないかと思ったので、プレーンなArray
への変換を強制し、それは私のために働いた。
Rails.cache.fetch([self.id, 'relA']) do
relA.where(
attr1: 'some_value'
).order(
'attr2 DESC'
).includes(
:rel_1,
:rel_2
).decorate.to_a
end
変更が完了したら、デフォルトのプロシージャを削除してください。何かのようなもの:
your_hash.default = nil # clear the default_proc