2010-03-22 8 views
40

모듈에서 class_eval을 사용하는 방법을 배우고 있는데 (나는 class_eval에 다소 익숙합니다) this helpful class in resource_controller을 발견했습니다. 거기에서 그들은이 같은 일이 :class_eval << - "end_eval", __FILE__, __LINE__은 Ruby에서 무엇을 의미합니까?

class_eval <<-"end_eval", __FILE__, __LINE__ 

    def #{block_accessor}(*args, &block) 
    unless args.empty? && block.nil? 
     args.push block if block_given? 
     @#{block_accessor} = [args].flatten 
    end 

    @#{block_accessor} 
    end 

end_eval 

__FILE____LINE__ 그 상황에서 무엇입니까? 나는 __FILE__가 현재 파일을 참조한다는 것을 알고 있지만 그 모든 일이 정확히 무엇을 하는가? 그걸 검색하는 방법을 모른다. :)

답변

50

__FILE____LINE__은 현재 실행중인 파일과 라인을 보유하는 일종의 동적 상수입니다. 여기에 전달하면 오류로 인해 위치가 올바르게보고됩니다. 이

$ ruby foo.rb 
foo.rb:5:in `send': undefined method `abc' for 123:Fixnum (NoMethodError) 
    from foo.rb:5:in `foo' 
    from foo.rb:11 

주를 실행하면

instance_eval <<-end_eval, __FILE__, __LINE__ 
    def foo 
    a = 123 
    b = :abc 
    a.send b 
    end 
end_eval 

foo 

는 그 평가 후면 단지 텍스트에도 불구하고 파일과 줄 # 5를 말한다. 그 파일/라인없이 출력은 다음과 같을 것이다 트릭 : 스택 추적은 단순히 도움이되지이다 (eval)을 보여줍니다

$ ruby foo.rb 
(eval):5:in `send': undefined method `abc' for 123:Fixnum (NoMethodError) 
    from (eval):5:in `foo' 
    from foo.rb:11 

.

+1

대신'define_method'를 사용하면 이런 종류의 트릭이 필요하지 않을 수도 있습니다. 취약점을 공개하지 않습니다 (http://stackoverflow.com/questions/3003328/how-do-i-use-class-eval/3003509#3003509 참조). –

3

<<heredoc의 시작입니다. 이 줄은 여러 줄 문자열의 시작 부분입니다. 문자열은 함수를 생성하기 위해 평가됩니다. class_eval 함수는 __FILE__ 및 __LINE__을 사용하여 디버그 정보를 추가합니다.

+1

하지만,하지만,하지만 ... 안그래 무정부 골프에서 골프 마법사? 루비를 손등처럼 알아야합니다! :-D (그것은 class_eval의 행동에 대한 성명서의 우스꽝 스러움에 대한 코멘트였습니다. 당신의 의도가 불확실하지 않다면, 제 의견을 다시 듣겠습니다.) –

+0

하하 ... 결코 그것이 너무 많은 문자이기 때문에 그 기능이 필요했습니다. –

+0

어떤 종류의 디버그 정보입니까? 어떻게 사용합니까? –

2

가능하면 eval- 문자열을 피하십시오. 특정 경우에, #class_exec#class_eval를 교체하는 것은 가능하며, 선호한다 :

class_exec do 
    define_method block_accessor do |*args, &block| 
    unless args.empty? && block.nil? 
     args.push block if block_given? 
     instance_variable_set "@#{block_accessor}", [args].flatten 
    end 
    instance_variable_get "@#{block_accessor}" 
    end 
end 
관련 문제