ruby on rails - रनटाइम पर विधि कहां परिभाषित की जाती है?
ruby-on-rails runtime (7)
हमें हाल ही में एक समस्या थी, जहां काम की एक श्रृंखला के बाद, एक बैकएंड प्रक्रिया चलाने में विफल रही। अब, हम अच्छे लड़के और लड़कियां थे और प्रत्येक चेक-इन के बाद rake test
चलाते थे, लेकिन रेल की लाइब्रेरी लोडिंग में कुछ विषमताओं के कारण, यह केवल तभी हुआ जब हमने उत्पादन मोड में सीधे मंगल से भाग लिया।
मैंने बग को ट्रैक किया और यह एक नए रेल मणि के कारण स्ट्रिंग क्लास में एक विधि को ओवरराइट करने के कारण था जिसने रनटाइम रेल कोड में एक संकीर्ण उपयोग तोड़ दिया।
वैसे भी, लंबी कहानी छोटी, रनटाइम पर, रूबी से पूछने का एक तरीका है जहां एक विधि परिभाषित की गई है? कुछ है whereami( :foo )
जो /path/to/some/file.rb line #45
? इस मामले में, मुझे बता रहा है कि इसे कक्षा स्ट्रिंग में परिभाषित किया गया था, क्योंकि यह कुछ लाइब्रेरी द्वारा ओवरलोड किया गया था।
मैं अपनी परियोजना में स्रोत जीवन की गारंटी नहीं दे सकता, इसलिए 'def foo'
लिए grepping मुझे जरूरी नहीं है कि मुझे क्या चाहिए, उल्लेख नहीं है कि मेरे पास कई def foo
, कभी-कभी मुझे रनटाइम तक नहीं पता कि मैं एक उपयोग कर सकते हैं।
आप ऐसा कुछ करने में सक्षम हो सकते हैं:
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 की सभी पुनः परिभाषाएं दिखाएगा। थोड़ा मेटा प्रोग्रामिंग के साथ, आप इसे जो भी काम करना चाहते हैं उसके लिए सामान्यीकृत कर सकते हैं। लेकिन फ़ाइल से पहले इसे लोड करने की आवश्यकता है जो वास्तव में पुनः परिभाषा करता है।
आप वास्तव में उपरोक्त समाधान से थोड़ा आगे जा सकते हैं। रूबी 1.8 एंटरप्राइज़ संस्करण के लिए, Method
उदाहरणों पर __file__
और __line__
विधियां हैं:
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
(धन्यवाद जोनाथन!) है:
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]
मेरे उत्तर को एक नए समान प्रश्न से कॉपी करना जो इस समस्या के लिए नई जानकारी जोड़ता है।
रुबी 1.9 में source_location नामक विधि है:
रूबी स्रोत फ़ाइल नाम और लाइन नंबर को इस विधि या शून्य से वापस करता है यदि यह विधि रूबी (यानी देशी) में परिभाषित नहीं की गई थी
इस मणि द्वारा इसे 1.8.7 तक वापस भेज दिया गया है:
तो आप विधि के लिए अनुरोध कर सकते हैं:
m = Foo::Bar.method(:create)
और फिर उस विधि के source_location
के लिए पूछें:
m.source_location
यह फ़ाइल नाम और रेखा संख्या के साथ एक सरणी वापस करेगा। ActiveRecord::Base#validates
इस रिटर्न को ActiveRecord::Base#validates
करता है:
ActiveRecord::Base.method(:validates).source_location
# => ["/Users/laas/.rvm/gems/[email protected]/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]
कक्षाओं और मॉड्यूल के लिए, रूबी समर्थन में निर्मित नहीं है, लेकिन वहाँ एक उत्कृष्ट गिस्ट है जो किसी दिए गए विधि के लिए फ़ाइल लौटने के लिए source_location
पर बनाता है या किसी विधि के लिए पहली फ़ाइल निर्दिष्ट नहीं होने पर कक्षा के लिए पहली फ़ाइल:
कार्रवाई में:
where_is(ActiveRecord::Base, :validates)
# => ["/Users/laas/.rvm/gems/[email protected]/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]
टेक्स्टमैट स्थापित मैक पर, यह निर्दिष्ट स्थान पर संपादक को भी पॉप अप करता है।
मैं इस धागे के लिए देर से आ रहा हूं, और हैरान हूं कि किसी ने Method#owner
उल्लेख नहीं किया है।
class A; def hello; puts "hello"; end end
class B < A; end
b = B.new
b.method(:hello).owner
=> A
यह मदद कर सकता है लेकिन आपको इसे स्वयं कोड करना होगा। ब्लॉग से चिपकाया गया:
रूबी एक method_added () कॉलबैक प्रदान करता है जिसे किसी भी समय कक्षा में एक विधि जोड़ा या फिर से परिभाषित किया जाता है। यह मॉड्यूल वर्ग का हिस्सा है, और प्रत्येक कक्षा एक मॉड्यूल है। Method_removed () और method_undefined () नामक दो संबंधित कॉलबैक भी हैं।
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby
यह वास्तव में देर हो चुकी है, लेकिन यहां बताया गया है कि आप कहां से एक विधि परिभाषित कर सकते हैं:
# 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)
#<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]
ध्यान दें कि यह देशी संकलित कोड की तरह सबकुछ पर काम नहीं करेगा। विधि वर्ग में कुछ साफ-सुथरे फ़ंक्शन भी हैं, जैसे Method#owner जो फ़ाइल को वापस लाता है जहां विधि परिभाषित की जाती है।
संपादित करें: __file__
और __line__
और अन्य उत्तर में आरईई के लिए नोट्स भी देखें, वे भी आसान हैं। - wg
caller()
का उपयोग करके आप हमेशा कहां से बैकट्रैक प्राप्त कर सकते हैं।