2011-07-28 16 views
5

[माणिक 1.8]रनटाइम पर गतिशील रूप से उदाहरण विधियों को कैसे बनाएँ?

मान लें मेरे पास है:

dummy "string" do 
    puts "thing" 
end 

अब, यह एक तरीका है जिसके इनपुट तर्क के रूप में एक स्ट्रिंग और एक ब्लॉक है के लिए एक कॉल है। अच्छा लगा।

अब मान लें कि मेरे पास बहुत सी कॉल (विभिन्न विधि नाम, एक ही तर्क) हो सकते हैं। उदाहरण:

otherdummy "string" do 
    puts "thing" 
end 

अब क्योंकि वे एक ही काम करते हैं, और वे सैकड़ों हो सकता है, मैं नहीं चाहता कि वांछित कक्षा में हर एक के लिए एक उदाहरण विधि बनाने चाहते हैं। मैं सामान्य नियम के आधार पर रनटाइम पर गतिशील रूप से विधि को परिभाषित करने का एक स्मार्ट तरीका खोजना चाहता हूं।

क्या यह संभव है? आमतौर पर कौन सी तकनीकों का उपयोग किया जाता है?

धन्यवाद

उत्तर

8

मैं method_missing का उपयोग करने का विशेष रूप से शौकीन हूँ, खासकर जब कोड का उपयोग करना चाहते विभिन्न विधि कॉल भर में बहुत समान है।

class ActiveRecord::Base 
    def method_missing(meth, *args, &block) 
    if meth.to_s =~ /^find_by_(.+)$/ 
     run_find_by_method($1, *args, &block) 
    else 
     super # You *must* call super if you don't handle the 
      # method, otherwise you'll mess up Ruby's method 
      # lookup. 
    end 
    end 

    def run_find_by_method(attrs, *args, &block) 
    # Make an array of attribute names 
    attrs = attrs.split('_and_') 

    # #transpose will zip the two arrays together like so: 
    # [[:a, :b, :c], [1, 2, 3]].transpose 
    # # => [[:a, 1], [:b, 2], [:c, 3]] 
    attrs_with_args = [attrs, args].transpose 

    # Hash[] will take the passed associative array and turn it 
    # into a hash like so: 
    # Hash[[[:a, 2], [:b, 4]]] # => { :a => 2, :b => 4 } 
    conditions = Hash[attrs_with_args] 

    # #where and #all are new AREL goodness that will find all 
    # records matching our conditions 
    where(conditions).all 
    end 
end 

define_method भी लगता है कि यह काम करेगा: जब भी किसी को कॉल x.boo और boo मौजूद नहीं है, method_missing boo करने के लिए boo साथ कहा जाता है, तर्क, और (वैकल्पिक) एक ब्लॉक - यहाँ इस site से एक उदाहरण है आपके लिए, लेकिन method_missing से मुझे इसके साथ कम अनुभव है। यहां एक ही लिंक से उदाहरण दिया गया है:

%w(user email food).each do |meth| 
    define_method(meth) { @data[meth.to_sym] } 
end 
+0

उपयोगी उदाहरण (मुझे लगता है कि रास्ते में विधि के नाम का प्रबंधन करने की जरूरत है भी) के लिए धन्यवाद। मैं निश्चित रूप से 'method_missing' विधियों के साथ जाउंगा जो पहले से नहीं जानते हैं। –

6

हां, कुछ विकल्प हैं।

पहला method_missing है। इसका पहला तर्क एक प्रतीक है जो कि विधि कहा जाता था, और शेष तर्क तर्क थे जिनका उपयोग किया गया था।

class MyClass 
    def method_missing(meth, *args, &block) 
    # handle the method dispatch as you want; 
    # call super if you cannot resolve it 
    end 
end 

दूसरा विकल्प गतिशील रूप से रनटाइम पर इंस्टेंस विधियों का निर्माण कर रहा है, अगर आप पहले से जानते हैं कि कौन सी विधियों की आवश्यकता होगी। इस वर्ग में किया जाना चाहिए, और एक उदाहरण इस तरह है:

class MyClass 
    1.upto(1000) do |n| 
    define_method :"method_#{n}" do 
     puts "I am method #{n}!" 
    end 
    end 
end 

यह एक आम पैटर्न define_method एक वर्ग विधि है जो रनटाइम पर नया उदाहरण तरीकों बनाने के लिए की जरूरत है में कहा जाता है।

+0

मुझे लगता है कि यह 'रखता है' मैं विधि # {n} हूं! "'। वैसे भी, अच्छा जवाब! –

+0

फिक्स्ड, धन्यवाद! –

+0

धन्यवाद। बहुत सराहना की। –

3

उपयोग define_method:

class Bar 
end 

bar_obj = Bar.new 

class << bar_obj 
define_method :new_dynamic_method do 
    puts "content goes here" 
end 
end 

bar_obj.new_dynamic_method 

आउटपुट:

content goes here 
संबंधित मुद्दे