Niedawno mieliśmy problem z tym, że po serii zatwierdzeń proces backendu nie został uruchomiony. Byliśmy dobrymi małymi chłopcami i dziewczynkami i biegaliśmy rake test
po każdym zameldowaniu, ale z powodu pewnych dziwnych cech w ładowaniu biblioteki Rails, pojawiło się to tylko wtedy, gdy uruchomiliśmy go bezpośrednio z Mongrel w trybie produkcyjnym.
Wyśledziłem błąd i było to spowodowane tym, że nowy klejnot Rails nadpisał metodę w klasie String w sposób, który przerwał jedno wąskie zastosowanie w kodzie wykonawczym Railsa.
W każdym razie, w skrócie, czy jest sposób, aby w czasie wykonywania zapytać Ruby, gdzie zdefiniowano metodę? Coś takiego whereami( :foo )
powraca /path/to/some/file.rb line #45
? W takim przypadku powiedzenie mi, że został zdefiniowany w klasie String, byłoby nieprzydatne, ponieważ zostało przeciążone przez jakąś bibliotekę.
Nie mogę zagwarantować, że źródło będzie żyło w moim projekcie, więc szukanie 'def foo'
go niekoniecznie da mi to, czego potrzebuję, nie wspominając o tym, że mam wiele def foo
, czasem nie wiem do czasu uruchomienia, z którego mogę korzystać.
źródło
Odpowiedzi:
Jest naprawdę późno, ale oto, jak znaleźć definicję metody:
http://gist.github.com/76951
Jeśli korzystasz z Ruby 1.9+, możesz użyć
source_location
Zauważ, że to nie działa na wszystko, na przykład na natywny kod skompilowany. Klasa metoda ma kilka funkcji, schludne, zbyt, jak Method # właściciela , która zwraca plik, w którym metoda jest zdefiniowana.
EDYCJA: Zobacz także
__file__
i__line__
i dla REE w drugiej odpowiedzi, one też są przydatne. - wgźródło
owner
metoda2.method(:crime)
?Fixnum
method_missing
. Więc jeśli masz klasę modułu lub przodka zclass_eval
lubdefine_method
wewnątrzmethod_missing
, to ta metoda nie będzie działać.Możesz faktycznie pójść nieco dalej niż powyższe rozwiązanie. W Ruby 1.8 Enterprise Edition jest
__file__
__line__
metody iMethod
instancje:Dla Ruby 1.9 i nowszych istnieje
source_location
(dzięki Jonathan!):źródło
__file__
i__line__
na każdejMethod
instancji klasy, ex:method(:method).__file__
.m.__file__
im.__line__
zostały zastąpione przezm.source_location
.Spóźniam się na ten wątek i jestem zaskoczona, że nikt o nim nie wspominał
Method#owner
.źródło
Method#parameters
.Kopiowanie mojej odpowiedzi z nowszego podobnego pytania, które dodaje nowe informacje do tego problemu.
Ruby 1.9 ma metodę o nazwie source_location :
Ten klejnot został przeniesiony do 1.8.7 :
Możesz więc poprosić o metodę:
A następnie poproś
source_location
o tę metodę:Zwróci tablicę z nazwą pliku i numerem linii. Np. Dla
ActiveRecord::Base#validates
tego zwrotu:W przypadku klas i modułów Ruby nie oferuje wbudowanej obsługi, ale istnieje doskonała Gist, która opiera się
source_location
na zwróceniu pliku dla danej metody lub pierwszego pliku dla klasy, jeśli nie określono żadnej metody:W akcji:
Na komputerach Mac z zainstalowanym programem TextMate powoduje to także wyświetlenie edytora w określonej lokalizacji.
źródło
To może pomóc, ale trzeba by to samemu zakodować. Wklejono z bloga:
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby
źródło
Jeśli możesz zawiesić metodę, otrzymasz ślad, który powie ci dokładnie, gdzie ona jest.
Niestety, jeśli nie możesz go zawiesić, nie możesz dowiedzieć się, gdzie został zdefiniowany. Jeśli spróbujesz małpować metodę, nadpisując ją lub zastępując, wtedy nastąpi awaria z nadpisanej lub zastąpionej metody i nie będzie to przydatne.
Przydatne sposoby zawieszania się metod:
nil
tam, gdzie to zabrania - przez większość czasu metoda podnosiArgumentError
lub zawsze obecnaNoMethodError
w klasie zero.źródło
require 'ruby-debug'; debugger
kod w miejscu, w którym chcesz wpaść.Może
#source_location
może pomóc ustalić, skąd pochodzi metoda.dawny:
Powrót
LUB
Powrót
źródło
Bardzo późna odpowiedź :) Ale wcześniejsze odpowiedzi mi nie pomogły
źródło
nil
?nil
.»Możesz być w stanie zrobić coś takiego:
foo_finder.rb:
Następnie upewnij się, że najpierw załadowano foo_finder z czymś takim
(Pomieszałem tylko z szynami, więc nie wiem dokładnie, ale wyobrażam sobie, że istnieje sposób, aby rozpocząć coś takiego.)
Spowoduje to wyświetlenie wszystkich ponownych definicji ciągu # foo. Przy odrobinie programowania można uogólnić go na dowolną funkcję. Ale należy go załadować PRZED plikiem, który faktycznie dokonuje ponownej definicji.
źródło
Zawsze możesz uzyskać informacje o tym, gdzie jesteś, używając
caller()
.źródło