2013-10-25 5 views
1

proc를 취하는 외부 서비스로 레일 요청을 캐시하려고합니다.Proc를 캐싱의 키로 사용하십시오.

2 개의 요청을 구분할 수 있도록하려면 proc이 레일스 캐시 키의 일부인 것이 중요합니다.

그러나 동일한 proc 및 proc 코드의 값을 가진 여러 요청은 매번 다른 proc 객체로 평가됩니다.

예는 :

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

따라서, 심지어 같은 요청에 대해 캐시 미스를 얻을.

코드와 변수 값 측면에서 procs가 동일하면 동일한 것으로 평가되는 캐시 키에서/proc 블록을 어떻게 사용합니까?

서비스 호출이

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 etc)

레일에서 이러한 유형의 캐싱을 수행하는 가장 좋은 방법은 무엇입니까?

P.S : 캐시

답변

0

당신이 다른 PROC 개체를 얻을 것이다 do ... end와 함께 인라인 블록을 정의 할 때마다로 Rails4 및 reddis를 사용

. 당신은 당신이 정확히 같은 PROC를 통해 보내는 절대적으로 확신 할 수 있도록 비켜 가야 할 것입니다 :

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

    call_service(&@my_call) 
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 

그래서 우리는

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> 

당신이 PROC 오브젝트에 대해 binding.eval('argument')를 호출 할 수 있습니다 인자의 상태를 얻으려면 objects-- 우리의 발동을 구축 할 수 있습니다. 이것은 Proc의 바인딩 컨텍스트에서 코드를 실행합니다.그래서 당신은

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 

을 say-- 수 그리고 분명히 당신은 비교할 수 있습니다 당신은 보편적 인 방법과 '바인딩에서 인수를 추출하는 방법이 필요 것

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

소스 locations-- d 비교를 위해 배열을 만들지 않고 해시를 결합하려고합니다 (예 : 'a.hash^b.hash^c.hash').

이것은 끔찍한 느낌입니다! 적어도 Procs에 :==을 무시하는 것은 나쁜 생각입니다.

관련 문제