2010-01-07 12 views
8

मुझे एक कक्षा की आवश्यकता है जिसमें अर्द्ध स्वचालित 'to_s' विधि है (वास्तव में एक्सएमएल उत्पन्न करने के लिए)।रूबी: attr_accessor जेनरेट किए गए तरीकों - उन्हें फिर से कैसे करें (to_s - कस्टम प्रारूप में)?

class MyClass 
    attr_accessor :id,:a,:b,:c 
end 

c=MyClass.new 

अब तक मैं एक बुनियादी कर रहा हूँ:

c.methods - Object.methods 

=> ["b", "b=", "c", "c=", "id=", "a", "a="] 

मैं कुछ चुनौतियों का सामना करना पड़ रहा मैं सभी स्वचालित तरीकों मेरे 'attr_accessor' लाइन में स्थापित के माध्यम से पुनरावृति करना चाहते हैं:

  1. 'आईडी' थोड़ा सिरदर्द का कारण बन सकता है - क्योंकि ऑब्जेक्ट में पहले से ही 'आईडी' लगता है।
  2. ऊपर 'c.methods' कॉल, स्ट्रिंग लौटाता है - मुझे कोई अन्य मेटा-डेटा नहीं मिल रहा है? (जावा 'विधि' में एक वस्तु है, जहां मैं और प्रतिबिंब कर सकता हूं)।
  3. मेरे पास एक-से-कई संबंध हैं जिनसे मुझे निपटना है ('सी' अन्य ऑब्जेक्ट प्रकारों का एक सरणी प्रकार है)।

यही वह है जो मैं करने की कोशिश कर रहा हूं: मैं एक साधारण ऑब्जेक्ट डिज़ाइन करना चाहता हूं जिसमें 'to_s' है जो एक XML खंड बनायेगा: उदाहरण के लिए।

<id> 1 </id> 
<a> Title </a> 
<b> Stuff </b> 
<c> 
    <x-from-other-object> 
    <x-from-other-object> 
    .... 
</c> 

और फिर इतना आसान वस्तु से अपने डेटा वर्गों के वारिस: इतना है कि (उम्मीद) मैं एक mechansim एक पूरे एक्सएमएल दस्तावेज़ बनाने के लिए मिलता है।

मुझे यकीन है कि मैं यहां भी पहिया का पुन: आविष्कार कर रहा हूं ... इसलिए अन्य कोशिश-परीक्षण और परीक्षणों का स्वागत है।

उत्तर

13

एक स्ट्रिंग से विधि वस्तुओं पाने के लिए आपको तरीकों का उपयोग कर सकते हैं method या instance_method (जहां method एक वर्ग पर एक वस्तु और instance_method पर कहा जा सकता है)। एकमात्र रोचक जानकारी जो आपको देता है वह धैर्य है, यद्यपि (जावा के विपरीत जहां यह आपको रिटर्न वैल्यू और तर्कों के प्रकार भी देगा, जो रूबी में निश्चित रूप से संभव नहीं है)।

आपका शीर्षक बताता है कि आप केवल attr_accessor द्वारा बनाई गई विधियों पर पुनरावृत्ति करना चाहते हैं, लेकिन आपका कोड आपकी कक्षा में परिभाषित हर विधि पर फिर से सक्रिय होगा, जो आपकी कक्षा में अतिरिक्त गैर-एक्सेसर विधियां जोड़ना चाहते हैं, जो एक समस्या हो सकती है ।

कि समस्या और id के साथ समस्या से छुटकारा पाने के लिए, आपको attr_accessor चारों ओर अपने स्वयं के आवरण इस्तेमाल कर सकते हैं जो भंडार जो चर इसके लिए accessors बनाया है, तो जैसे:

module MyAccessor 
    def my_attr_accessor *attrs 
    @attrs ||= [] 
    @attrs << attrs 
    attr_accessor *attrs 
    end 

    def attrs 
    @attrs 
    end 
end 

class MyClass 
    extend MyAccessor 
    my_attr_accessor :id,:a,:b,:c 

    def to_s 
    MyClass.attrs.each do |attr| 
     do_something_with(attr, send(attr)) 
    end 
    end 
end 

समस्या 3 के लिए तुम सिर्फ कर सकते हैं

if item.is_a? Array 
    do_something 
else 
    do_something_else 
end 
+0

दिलचस्प सामान पर आधारित है! धन्यवाद! – monojohnny

+0

इसने निश्चित रूप से +1 की मदद की है - लेकिन यहां मुख्य मुद्दा यह है कि मैं वास्तव में attr_accessor- परिभाषित सामानों को वास्तव में चुनना चाहता हूं। – monojohnny

+0

ने इसे इंगित करने के लिए विवरण को थोड़ा सा स्पष्ट किया है। – monojohnny

0

मैं कस्टम तकनीक को जेएसओएन में परिवर्तित करने के लिए इस तकनीक का उपयोग करता हूं। नीचे दिए गए स्निपेट सहायक होंगे क्योंकि प्रश्न to_xml कार्यान्वयन के लिए था।

मॉड्यूल में self.included का उपयोग करके यहां एक छोटा जादू है। यहां मॉड्यूल के बारे में 2006 से एक बहुत अच्छा लेख है जिसमें मॉड्यूल और क्लास विधियों दोनों http://blog.jayfields.com/2006/12/ruby-instance-and-class-methods-from.html

मॉड्यूल को to_json कार्यक्षमता प्रदान करने के लिए किसी भी कक्षा में शामिल करने के लिए डिज़ाइन किया गया है। मौजूदा वर्गों के लिए न्यूनतम परिवर्तन की आवश्यकता के लिए यह attr_accessor विधि को स्वयं का उपयोग करने के बजाय हस्तक्षेप करता है।जरूरत इससे पहले कि मैं मतदान कर सकते हैं इस के माध्यम से जाना -

to_json कार्यान्वयन इस answer

module JSONable 
    module ClassMethods 
    attr_accessor :attributes 

    def attr_accessor *attrs 
     self.attributes = Array attrs 
     super 
    end 
    end 

    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    def as_json options = {} 
    self.class.attributes.inject({}) do |hash, attribute| 
     hash[attribute] = self.send(attribute) 
     hash 
    end 
    end 

    def to_json *a 
    as_json.to_json *a 
    end 
end 


class CustomClass 
    include JSONable 
    attr_accessor :b, :c 

    def initialize b: nil, c: nil 
    self.b, self.c = b, c 
    end 
end 

a = CustomClass.new(b: "q", c: 23) 
puts JSON.pretty_generate a 

{ 
    "b": "q", 
    "c": 23 
} 
संबंधित मुद्दे