문제

우리는 최근 일련의 커밋이 발생한 후 백엔드 프로세스가 실행되지 않은 문제가있었습니다. 이제 우리는 좋은 작은 소년과 소녀 였고 rake test 모든 체크인 후에도 Rails의 라이브러리 로딩의 이상한 점으로 인해 생산 모드에서 Mongrel에서 직접 실행할 때만 발생했습니다.

나는 버그를 추적했고 그것은 런타임 레일 코드에서 하나의 좁은 용도를 깨뜨리는 방식으로 문자열 클래스의 메소드를 덮어 쓰는 새로운 레일 보석으로 인한 것이 었습니다.

어쨌든, 긴 이야기가 짧아지면, 런타임에 방법이 어디에서 정의되었는지 루비에게 물어볼 방법이 있습니까? 같은 것 whereami( :foo ) 그것은 돌아옵니다 /path/to/some/file.rb line #45? 이 경우 클래스 문자열로 정의되었다고 말하는 것은 일부 라이브러리에 의해 과부하 되었기 때문에 도움이되지 않을 것입니다.

나는 내 프로젝트에 소스가 살고 있다고 보장 할 수 없으므로 'def foo' 내가 가지고 있다면 말할 것도없이 반드시 필요한 것을 줄 필요는 없습니다. 많은 def fooS, 때로는 런타임까지 내가 어떤 사용을 사용하고 있는지 알지 못합니다.

도움이 되었습니까?

해결책

이것은 실제로 늦었지만 방법이 정의되는 위치를 찾을 수있는 방법은 다음과 같습니다.

http://gist.github.com/76951

# How to find out where a method comes from.
# Learned this from Dave Thomas while teaching Advanced Ruby Studio
# Makes the case for separating method definitions into
# modules, especially when enhancing built-in classes.
module Perpetrator
  def crime
  end
end

class Fixnum
  include Perpetrator
end

p 2.method(:crime) # The "2" here is an instance of Fixnum.
#<Method: Fixnum(Perpetrator)#crime>

루비 1.9+에 있다면 사용할 수 있습니다 source_location

require 'csv'

p CSV.new('string').method(:flock)
# => #<Method: CSV#flock>

CSV.new('string').method(:flock).source_location
# => ["/path/to/ruby/1.9.2-p290/lib/ruby/1.9.1/forwardable.rb", 180]

원시 컴파일 코드와 같은 모든 것이 작동하지 않습니다. 그만큼 방법 클래스 같은 깔끔한 기능도 있습니다 방법#소유자 메소드가 정의 된 파일을 반환합니다.

편집 : 또한 참조하십시오 __file__ 그리고 __line__ 그리고 Ree에 대한 메모는 다른 답변에서도 편리합니다. -WG

다른 팁

실제로 위의 솔루션보다 조금 더 나아갈 수 있습니다. Ruby 1.8 Enterprise Edition의 경우 __file__ 그리고 __line__ 방법 Method 인스턴스 :

require 'rubygems'
require 'activesupport'

m = 2.days.method(:ago)
# => #<Method: Fixnum(ActiveSupport::CoreExtensions::Numeric::Time)#ago>

m.__file__
# => "/Users/james/.rvm/gems/ree-1.8.7-2010.01/gems/activesupport-2.3.8/lib/active_support/core_ext/numeric/time.rb"
m.__line__
# => 64

루비 1.9 이상의 경우에는 있습니다 source_location (감사합니다 Jonathan!) :

require 'active_support/all'
m = 2.days.method(:ago)
# => #<Method: Fixnum(Numeric)#ago>    # comes from the Numeric module

m.source_location   # show file and line
# => ["/var/lib/gems/1.9.1/gems/activesupport-3.0.6/.../numeric/time.rb", 63]

나는이 스레드에 늦게 와서 아무도 언급하지 않았다는 것에 놀랐다. Method#owner.

class A; def hello; puts "hello"; end end
class B < A; end
b = B.new
b.method(:hello).owner
=> A

새로부터 내 대답을 복사합니다 비슷한 질문 이 문제에 새로운 정보가 추가됩니다.

루비 1.9 메소드가 호출되었습니다 Source_location:

루비 에서이 방법을 포함하는 루비 소스 파일 이름과 라인 번호를 반환합니다.

이것은 백포링되었습니다 1.8.7 이 보석에 의해 :

따라서 방법을 요청할 수 있습니다.

m = Foo::Bar.method(:create)

그런 다음 요청하십시오 source_location 그 방법의 :

m.source_location

이것은 파일 이름과 줄 번호로 배열을 반환합니다. 예를 들어 ActiveRecord::Base#validates 이것은 반환됩니다 :

ActiveRecord::Base.method(:validates).source_location
# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0@arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]

클래스와 모듈의 경우 Ruby는 내장 지원을 제공하지 않지만 그에 따라 쌓이는 훌륭한 요점이 있습니다. source_location 지정된 메소드가 지정되지 않은 경우 주어진 메소드 또는 클래스의 첫 번째 파일을 반환하려면 다음과 같습니다.

행동 :

where_is(ActiveRecord::Base, :validates)

# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0@arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]

TextMate가 설치된 Mac에서는 지정된 위치에서 편집기가 나타납니다.

이것은 도움이 될 수 있지만 직접 코딩해야합니다. 블로그에서 붙여 넣기 :

Ruby는 클래스 내에서 메소드가 추가되거나 재정의 될 때마다 호출되는 Method_added () 콜백을 제공합니다. 모듈 클래스의 일부이며 모든 클래스는 모듈입니다. Method_removed () 및 Method_undefined ()라는 두 개의 관련 콜백이 있습니다.

http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby

방법을 충돌시킬 수 있다면 방법이 어디에 있는지 정확히 알려주는 백 트레이스를 얻을 수 있습니다.

불행히도, 당신이 그것을 충돌시킬 수 없다면, 당신은 그것이 정의 된 위치를 찾을 수 없습니다. 이를 덮어 쓰거나 재정의하여 방법으로 원숭이를 시도하면, 모든 충돌은 덮어 쓰기 또는 재정의 메소드에서 나옵니다.

충돌 방법의 유용한 방법 :

  1. 통과하다 nil 그것이 그것을 금지하는 곳 - 많은 시간이 그 방법이 ArgumentError 또는 항상 존재합니다 NoMethodError nil 클래스에서.
  2. 이 방법에 대한 내부 지식이 있고 방법이 다른 방법을 호출한다는 것을 알고 있다면 다른 메소드를 과도하게 쓰고 그 안으로 올릴 수 있습니다.

아마도 #source_location 방법의 출처를 찾는 데 도움이 될 수 있습니다.

전:

ModelName.method(:has_one).source_location

반품

[project_path/vendor/ruby/version_number/gems/activerecord-number/lib/active_record/associations.rb", line_number_of_where_method_is]

또는

ModelName.new.method(:valid?).source_location

반품

[project_path/vendor/ruby/version_number/gems/activerecord-number/lib/active_record/validations.rb", line_number_of_where_method_is]

매우 늦은 답변 :) 그러나 이전 답변은 나를 도와주지 않았습니다.

set_trace_func proc{ |event, file, line, id, binding, classname|
  printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
# call your method
set_trace_func nil

다음과 같은 일을 할 수 있습니다.

foo_finder.rb :

 class String
   def String.method_added(name)
     if (name==:foo)
        puts "defining #{name} in:\n\t"
        puts caller.join("\n\t")
     end
   end
 end

그런 다음 foo_finder가 먼저와 같은 것으로로드되도록하십시오

ruby -r foo_finder.rb railsapp

(나는 레일 만 엉망이되었으므로 정확히 알지 못하지만 이런 식으로 시작하는 방법이 있다고 생각합니다.)

이것은 문자열#foo의 모든 재정의를 보여줄 것입니다. 약간의 메타 프로그래밍을 사용하면 원하는 기능에 대해 일반화 할 수 있습니다. 그러나 실제로 재정의를 수행하는 파일 전에로드해야합니다.

당신은 항상 당신이 사용하여 어디에있는 backtrace를 얻을 수 있습니다. caller().

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top