2013-10-25 68 views
1

我試圖緩存rails請求到需要proc的外部服務。使用Proc作爲緩存的關鍵

對於我來說,能夠區分2個請求,它的重要性在於proc是Rails緩存鍵的一部分。

但是,具有相同proc和proc代碼中的值的多個請求仍然會每次評估爲不同的proc對象。

如:

#<Proc:[email protected]/Users/app/development/work/runner.rb:10> 
#<Proc:[email protected]/Users/app/development/work/runner.rb:10> 

因此,我得到高速緩存未命中即使是同樣的請求。

如何在緩存鍵中使用block/proc,如果procs在代碼和變量值方面相同,則評估結果相同。

服務電話是一樣的東西

def some_method  
    call_service do 
    a= 3; 
    b=6 
    end 
end 

def call_service(block) 
     Rails.cache.fetch(Date.today, block) { 
     external_service(&block) 
     } 
    end 

I want to be able to compare blocks : 
eg 
{a=3, a*a} == {a=3, a*a} => True 
{a=3, a*a} == {a=4, a*a} => false 
{a=3, a*a} == {a=4, a*a*a} => False 

我試圖用,

block.source 
RubyVM::InstructionSequence.of(block).disasm 

但他們沒有抓住塊的狀態,即變量的值(A = 3等等)

在rails中實現這種類型的緩存的最佳方式是什麼?

P.S:

使用Rails4和reddis作爲緩存

回答

0

每次定義內嵌塊do ... end你會得到一個不同 PROC對象的時間。你將不得不走出自己的路是絕對肯定你有過一樣的PROC發送:

def some_method  
    @my_call ||= lambda { 
    a = 3 
    b = 6 
    } 

    call_service(&@my_call) 
end 

這可能是從一開始就壞主意。你會更好做的是傳遞一個緩存鍵:

call_service("3/6") do 
    # ... 
end 

然後你緩存反對這種一致的關鍵,而不是任意PROC。

0

這樣你可能會得到一些里程數。這個函數返回一個簡單的Proc對象。該對象將有一個源位置和一個綁定,其中包含構建Proc時參數a,b和c的狀態。

def build_proc(a, b, c) 
    Proc.new { puts "I was built with params #{a} #{b} #{c}!" } 
end 

因此,我們可以建立我們的PROC objects--

2.0.0-p195 :121 > p1 = build_proc(1, 2, 3) 
=> #<Proc:[email protected](irb):118> 
2.0.0-p195 :122 > p2 = build_proc(2, 4, 6) 
=> #<Proc:[email protected](irb):118> 

爲了讓您可以撥打binding.eval('argument')對一個Proc對象參數的狀態。這將在Proc綁定的上下文中運行代碼。所以,你可以say--

p1.binding.eval('[a, b, c]') == p2.binding.eval('[a, b, c]') 

2.0.0-p195 :127 > p1.binding.eval('[a, b, c]') == p2.binding.eval('[a, b, c]') 
=> false 
2.0.0-p195 :128 > p2 = build_proc(1, 2, 3) 
=> #<Proc:[email protected](irb):118> 
2.0.0-p195 :129 > p1.binding.eval('[a, b, c]') == p2.binding.eval('[a, b, c]') 
=> true 

而且很明顯,你可以比較源locations--

p1.source_location == p2.source_location && 
p1.binding.eval('[a, b, c]') == p2.binding.eval('[a, b, c]') 

你會需要一種方法來提取出的參數在一個普遍的方式和你」的結合d想要組合它們的散列而不是構建一個用於比較的數組(例如'a.hash^b.hash^c.hash')。

雖然這感覺很糟糕!至少,在Procs上重寫:==可能是一個壞主意。

相關問題