2011-05-05 4 views
2

이 특정 방법은 응용 프로그램이 중단 원인이된다런타임에 Ruby 메서드가 호출되는 위치는 어떻게 찾습니까?

# controller 
def new 
    @view_mode = :new 
    template = "new" 
    render template, :layout => false 
end  

# new.haml 
- details_view @user do |b, f| 

# build_helper 
def details_view(model, options = {}, &block) 
    # instantiate OptionsWrapper passing a hash of key/value pairs, in this case 
    # an empty hash. OptionsWrapper contains a method_missing method so when we 
    # invoke mode on our instance of OptionsWrapper, since it does not contain 
    # instance method of mode, it invokes method_missing and we set a number of 
    # methods on fly. 
    options = OptionsWrapper.new(options) 
    options.mode ||= @view_mode 
    model_name = model.class.model_name.singular.dasherize 
    options.dom_id = "#{model_name}-details-view" 
    # we instantiate DetailsViewBuilder passing in a few arguments (e.g. new, 
    # ActionView, user) to the constructor method. 
    builder = DetailsViewBuilder.new(options.mode, self, model) 
    options.html ||= {} 
    options.html[:id] ||= nil 
    options.html[:class] = "x-#{options.mode} #{options.html[:class]}".strip 
    render :layout => "shared/details_view", :locals => {:builder => builder, 
    :model => model, :options => options}, &block 
end 

#details_view_builder 
class DetailsViewBuilder 
    attr_accessor :mode, :template, :model, :form 

    def initialize(mode, template, model) 
    @mode, @template, @model = mode, template, model #new, ActionView, user 
    end 

    def to_s 
    # here's the method causing error! 
    "#{self.class.name.underscore}__#{object_id}" 
    end 
end 

# we then render the details_view passing in some locals as shown a 
# few lines above: 
.details-dialog{:id => options.dom_id } 
    case options.mode 
    - when :new 
- form_for model, options.slice(:url, :html) do |form| 
    = yield builder, form 

:

ActionView::TemplateError (`@content_for_details_view_builder__2234321380' is not allowed as an instance variable name) in app/views/shared/_details_view.haml: 

기본적으로 여기에 위의 예외까지 이어지는 코드 실행의 : 다음과 같은 오류와

# needed becasuse of a rails bug 
def to_s 
    "#{self.class.name.underscore}__#{object_id}" 
end 

나는 to_s 메서드가 오류를 일으키는 지 100 % 확신하고 있습니다. 이 오류의 원인이 어디에서 호출되는지는 확실하지 않습니다. 위의 통지는 빌더 변수를 산출합니다. 해당 빌더 변수에는이 메소드가있는 클래스가 들어 있습니다. 콜 스택을 투명하게 볼 수 있도록 요소를 검사하는 더 좋은 방법을 찾아야하며 메서드가 주어진다면 어디에서 호출되는지 알 수 있습니다. 이상하게도이 방법은 로컬 컴퓨터에서 작동하지만 서버에서 프로덕션 오류가 발생합니다. 나는 또한 여기에 질문을하지만 대답에 만족하지 않았다

ActionView::TemplateError 
(`@content_for_details_view_builder__-626960428' is not allowed as an 
instance variable name) in app/views/shared/_details_view.haml: 

searchlogic (2.4.27) lib/searchlogic/rails_helpers.rb:75:in 
`fields_for' 
searchlogic (2.4.27) lib/searchlogic/rails_helpers.rb:64:in 
`form_for' 
app/helpers/builders_helper.rb:68:in `details_view' 
/home/app-sptr/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/benchmark.rb:308:in 
`realtime' 
app/other/restful_component.rb:488:in `new_html' 
app/other/restful_component.rb:73:in `new' 
app/other/restful_component.rb:72:in `new' 
/home/app-sptr/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/benchmark.rb:308:in 
`realtime' 
rack (1.1.2) lib/rack/head.rb:9:in `call' 
rack (1.1.2) lib/rack/methodoverride.rb:24:in `call' 
rack (1.1.2) lib/rack/lock.rb:11:in `call' 
rack (1.1.2) lib/rack/lock.rb:11:in `synchronize' 
rack (1.1.2) lib/rack/lock.rb:11:in `call' 

: http://www.ruby-forum.com/topic/1641800#new

답변

5

caller()을 사용하면 특정 방법으로 스택 추적을 파악할 수 있습니다. 그러나 나는 또한 문제에 대한 해결책을 (내가 생각하기에) 공유 할 것입니다.

to_s 메서드는 인스턴스 변수를 으로 설정하는 데 사용되는 문자열을 반환합니다. DetailsViewBuilderobject_id은 변수 이름의 일부입니다. 객체 ID는 메모리에있는 객체의 위치를 ​​나타냅니다. 직관과는 반대로, 객체의 object_id은 때때로 음수 인 일 수 있습니다. 이 문제가 발생하는지 여부는 플랫폼 종속 일 수도 있습니다. 따라서 프로덕션 환경에서만이 오류가 표시됩니다. 음수 객체 ID는 인스턴스 변수 이름이 @content_for_details_view_builder__-626960428과 같아 지도록합니다. 여기에는 대시가 포함됩니다. 루비에서 식별자의 일부로 대시가 허용되지 않습니다.. 따라서 오류.

어쨌든 content_for의 인수로 DetailsViewBuilder의 인스턴스를 사용하는 것 같습니다. 맞습니까? 또는 사용중인 일부 라이브러리에서 간접적으로 발생할 수 있습니다.

어떤 경우이든 이것이 올바른 동작이고 원하는 경우 인스턴스 변수 이름 오류가 발생하지 않도록하려면 수정이 간단합니다.인스턴스 변수 결코 대시를 포함하지 않는 것을 보장하기 위해 object_id.absobject_id 변경 :

def to_s 
    "#{self.class.name.underscore}__#{object_id.abs}" 
end 
+0

귀하의 모든 권고는 여기에했다. 이것은 확고한 대답이었습니다. – JohnMerlino

0

당신이 게시 된 링크에 caller()를 사용하는 제안, 실제로 매우 좋은 여기에 역 추적의 재미있는 이야기입니다.

워드 프로세서 괜찮은 예제를 가지고 있지만, 당신이 놓친 것 같다 것은이 부분이었다

The optional start parameter determines the number of initial stack entries to omit from the result.

은 기본적으로 caller()은 당신이 할 수있는, 당신이 처리되지 않은 예외를 얻을 것 스택 추적의 용기입니다 얼마나 많은 줄을 표시해야하는지 말하십시오.

관련 문제