2010-03-22 25 views
40

मैं कैसे मॉड्यूल में class_eval उपयोग करने के लिए सीख रहा हूँ (मैं class_eval साथ कुछ हद तक परिचित हूँ) और this helpful class in resource_controller बारे में जाना। वहाँ में वे इस तरह बातें हैं:क्या class_eval << करता है - "end_eval", __FILE__, __LINE__ रूबी में क्या मतलब है?

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__ गतिशील स्थिरांक हैं जो वर्तमान में निष्पादित फ़ाइल और रेखा को पकड़ते हैं। यहां उन्हें पास करने से त्रुटियों को उनके स्थान की उचित रिपोर्ट करने की अनुमति मिलती है।

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

foo 

यह कहता है कि फाइल और लाइन # 5 कि भले ही सिर्फ एक eval में पाठ था जब आप इस

$ 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 

नोट चलाते हैं। उन फ़ाइल/लाइन के बिना चाल उत्पादन इस प्रकार दिखाई देगा:

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

स्टैक ट्रेस बस के रूप में उपयोगी नहीं है (eval) को दर्शाता है।

+1

यह उल्लेख करना अच्छा होगा कि इसके बजाय 'define_method' का उपयोग करने के लिए इस तरह की चाल की आवश्यकता नहीं होगी, साथ ही यह भेद्यताएं नहीं खोलेंगे (http://stackoverflow.com/questions/3003328/how-do-i-use-class-eval/3003509#3003509 देखें) –

3

<< एक heredoc की शुरुआत है। वह रेखा एक मल्टीलाइन स्ट्रिंग की शुरुआत है। स्ट्रिंग को फ़ंक्शन बनाने के लिए निकाला जाता है। class_eval समारोह __FILE__ और __LINE__ डिबग जानकारी जोड़ने के लिए उपयोग करता है।

+1

लेकिन लेकिन लेकिन नहीं आप अराजकता गोल्फ से गोल्फ जादूगर: अपने विशेष मामले में, #class_exec साथ #class_eval की जगह संभव है, और प्राथमिकता दी जानी चाहिए? आपको रूबी को अपने हाथ की पीठ की तरह जानना चाहिए! :- डी (यह आपके बयान की इच्छा-धोखाधड़ी पर एक टिप्पणी थी कि 'class_eval' का व्यवहार क्या है। यदि आपका इरादा अनिश्चित नहीं था, तो मैं अपनी टिप्पणी वापस लेता हूं।) –

+0

हाहा ... मैंने कभी नहीं उस कार्य की आवश्यकता है क्योंकि यह बहुत सारे पात्र थे। –

+0

किस तरह की डीबग जानकारी? मैं इसे कैसे इस्तेमाल करूं? –

2

के भी ध्यान दें, जहां संभव है कि eval -ling तार से बचा जाना चाहिए करते हैं। ...

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 
संबंधित मुद्दे