1

필자는 ActiveRecord 쿼리에서 반환 된 레코드를 근본적으로 수정하는 Rails 3 gem을 빌드하고있다. 내가하고있는 일 중 하나는 method_missingrespond_to? 메서드를 재정의하지만 내 respond_to? 정의에서 "SystemStackError : stack level too deep"오류가 발생하는 무한 루프가 발생하는 것으로 보입니다. 여기 Object.respond_to? 무한 루프에 갇혀있다

내 원래 이러한 방법의 정의입니다 :이 붙어 점점 곳이 무한 루프가 발생하는 이유를 배우려고 노력에서

def respond_to?(name, *args) 
    super(name, *args) || parent_association.respond_to?(name) 
end 

def method_missing(name, *args, &block) 
    if parent_association.respond_to?(name) 
    parent_association.send(name, *args, &block) 
    else 
    super(name, *args, &block) 
    end 
end 

def parent_association 
    send(parent_association_name) # Essentially yields another ActiveRecord 
           # instance (e.g.: instance of User), but 
           # never returns itself. 
end 

, 내가보고 출력 "후"약간의 "이전"과 함께 respond_to? 구조 조정 .

before (_run__374051839217347232__initialize__1707831318230746190__callbacks) 
after 
before (_run__374051839217347232__validation__1707831318230746190__callbacks) 
after 
before (_run__374051839217347232__validate__1707831318230746190__callbacks) 
after 
before (_run__374051839217347232__save__1707831318230746190__callbacks) 
after 
before (_run__374051839217347232__create__1707831318230746190__callbacks) 
after 
before (created_at) 
after 
before (created_on) 
after 
... 

그러나 언제든지 나는 것을하는 찾기 콜백을 참조하십시오

def respond_to?(name, *args) 
    return true if super(name, *args) 
    puts "before (#{name})" 
    result = parent_association.respond_to?(name) 
    puts "after" 
    result 
end 

실행

, 예상대로 다양한 콜백과 각에 대한 전과 호출 후 하나와 실행 방법을 속성 것으로 보인다 무한 루프에 걸린 것으로 나타납니다 :

before (_run__374051839217347232__find__1707831318230746190__callbacks) 
before (_run__374051839217347232__find__1707831318230746190__callbacks) 
before (_run__374051839217347232__find__1707831318230746190__callbacks) 
before (_run__374051839217347232__find__1707831318230746190__callbacks) 
before (_run__374051839217347232__find__1707831318230746190__callbacks) 
before (_run__374051839217347232__find__1707831318230746190__callbacks) 
before (_run__374051839217347232__find__1707831318230746190__callbacks) 
before (_run__374051839217347232__find__1707831318230746190__callbacks) 
... 
SystemStackError: stack level too deep 

respond_to?, 그때 모든 것이 원활하게 실행하기 위해 나타납니다 해킹하는 경우 :

def respond_to?(name, *args) 
    return true if super(name, *args) 
    return false if name =~ /^_run_.*_find_.*_callbacks$/ 
    parent_association.respond_to?(name) 
end 

무엇이 내가이 해킹이 필요한 것일까 요? 어떻게 피할 수 있습니까? parent_association 새로운 AR 객체를 반환하는 경우

답변

0

AR 새로운 객체를 생성 할 것이다 respond_to?, 등 ... 호출 그래서에 respond_to?를 호출하여 해킹을 상속합니다 이 함수는 :

belongs_to :employee 
01 :

def parent_association 
    send(parent_association_name) # Essentially yields another ActiveRecord 
           # instance (e.g.: instance of User), but 
           # never returns itself. 
end 

가변 parent_association_name 같은 것을 통해 정의 employee 같은이며

찾기 콜백이 실행될 때까지 employee이 모델 인스턴스에 정의되어 있지 않기 때문에 (원래 질문에 포함되지 않은 코드에서) 찾기 콜백이 호출되기 전에 자리에 respond_to?을 처음 호출했기 때문에 send(parent_assocation_name)respond_to?에 대한 재귀 호출이 발생했습니다.

+1

정확한 언어를 사용하면 더 명확 해집니다. 'parent_association_name'은 변수가 아니며'employee'가 항상 정의되어 있다고 생각합니다.로드되지 않았을 수도 있습니다. 실제로 "콜백"을 의미하는지 확신 할 수 없습니다. 나는 당신이 묘사하고있는 것이 내가 말하는 것과 당신이 그것을 어떻게 고쳐 놓았는지에 대해 아직도 확실하지 않습니다. –

0

, 또한 문제가되고 결국

+0

실제로 생성 된 다른 ActiveRecord 객체가이 메소드를 구현하는 경우 사실이 아닙니다.이 경우는 여기에 해당됩니다. 예를 들어 다른 AR 객체에는 원래 AR 객체에 없었던 (구현 된 속성 때문에)'.name'과 같은 메소드가 있습니다. 메소드가 실제로 객체에 정의되어 있기 때문에 어떤 점에서는'super'를 호출하고 리턴 할 것입니다. –

+0

후속 조치를 취하기 위해'respond_to? '를 통해 재귀가 끝났지 만 언급 한 것처럼 별도의 AR 객체에서 재귀 적으로 정의되지 않는 함수라는 문제는 아닙니다. –

관련 문제