2011-03-05 11 views
11

के साथ बुलाया जाता है I after_initialize का उपयोग करके किसी ऑब्जेक्ट के लिए कुछ डिफ़ॉल्ट मान सेट करने का प्रयास कर रहा हूं। मेरी समस्या यह है कि मैं यह कहूंगा कि वस्तु को कैसे बनाया जाए, इससे कोई फर्क नहीं पड़ता।रेल 3 को बाद में शुरू नहीं किया जाता है जब ब्लॉक को

मेरी कक्षा:

class Foo < ActiveRecord::Base 

    serialize :data 

    after_initialize :init 

    def init 
    self.data ||= {} 
    self.bar ||= "bar" 
    self.baz ||= "baz" 
    end 

end 

सब कुछ ठीक काम करता है अगर मैं Foo.new, Foo.new(:bar => "things") और Foo.create(:baz => 'stuff') कहते हैं। हालांकि जब मैं createafter_initialize के साथ ब्लॉक का उपयोग करता हूं तो कॉलबैक नहीं चलाया जाता है।

obj = Foo.create do |f| 
    f.bar = "words" 
    f.data = { :attr_1 => 1, :attr_2 => 2 } 
end 

यह सिर्फ obj.baz =>nil बजाय की अन्य विशेषताओं को ठीक से सेट के साथ "baz" अर्जित करता है।

क्या मुझे कॉलबैक निष्पादित करने के तरीके से कुछ याद आ रहा है, कॉल के साथ कॉल करने के साथ मतभेदों के साथ अंतर और ब्लॉक के बिना डिफ़ॉल्ट मूल्यों के बिना या डिफ़ॉल्ट हैं?

अद्यतन

मिले मुद्दा।

यह पता चला है कि ब्लॉक के साथ create को कॉल करना और बिना अलग हैं। जब आप किसी ब्लॉक के बिना create पर कॉल करते हैं और केवल पैरामीटर के हैश में पास करते हैं, तो सभी उद्देश्यों और उद्देश्यों के लिए आप Foo.new({<hash of argument>}).save पर कॉल कर रहे हैं, और after_initialize कॉलबैक आपको सहेजने से पहले ठीक से निष्पादित किया जाता है।

जब आप ब्लॉक के साथ create पर कॉल करते हैं तो कुछ अलग होता है। घटनाओं का क्रम Foo.new को आपके द्वारा पारित किए गए तर्कों के साथ बुलाया जाता है, फिर after_initialize कॉल किया जाता है, फिर ब्लॉक चला जाता है। तो यदि आप ब्लॉक का उपयोग कर रहे हैं (जैसा कि मैं था) हैश पैरामीटर के साथ एक दूसरे के साथ एक दूसरे के लिए एक-दूसरे को और अधिक पठनीय बनाने के लिए आप थोड़ा सा प्राप्त कर सकते हैं क्योंकि आपके after_initialize आपके द्वारा निर्धारित किए जाने वाले सभी पैरामीटर वास्तव में सेट किए जाने से पहले चलाया जाता है।

मुझे थोड़ा सा मिला क्योंकि मैं after_initialize में कुछ अतिरिक्त काम कर रहा था जो कुछ अतिरिक्त आवश्यक विशेषताओं को पारित करने के मूल्य के आधार पर सेट कर रहा था। चूंकि after_initialize को कॉल करने के बाद वास्तव में कुछ भी सेट नहीं किया गया था, कुछ भी सही ढंग से सेट नहीं हुआ और मेरी मान्यताओं में विफल रहा।

मैं init पर कॉल करने के लिए समाप्त हुआ। एक बार after_initialize और एक बार before_validation पर। सबसे साफ नहीं, लेकिन इस मुद्दे को हल किया।

धन्यवाद सही दिशा में मुझे इंगित करने के लिए ब्रैंडन पर जाएं।

+0

यदि आप वही काम करते हैं लेकिन 'Foo.new' (यानी घोषणा की ब्लॉक विधि के साथ), क्या वही होता है? –

+0

एक ब्लॉक के साथ Foo.new बस ठीक काम करता है। – HMCFletch

+0

@ एचएमसीएफलेट - क्या हो रहा है की महान व्याख्या - –

उत्तर

7

मैं इसे पुन: उत्पन्न करने में असमर्थ हूं।

ruby-1.9.2-p136 :001 > obj = Service.create do |s| 
ruby-1.9.2-p136 :002 >  s.token = "abc" 
ruby-1.9.2-p136 :003?> end 
=> #<Service id: 22, user_id: nil, type: nil, data: {}, created_at: "2011-03-05 04:18:00", updated_at: "2011-03-05 04:18:00", token: "abc"> 
ruby-1.9.2-p136 :004 > obj.data 
=> {} 

आप देख सकते हैं, data के रूप में एक खाली हैश को after_initialize विधि में प्रारंभ:

class Service < ActiveRecord::Base 
    serialize  :data, Hash 
    after_initialize :create_default_data 
    attr_accessible :data, :token 

    protected 

    def create_default_data 
     self.data ||= Hash.new 
    end 
end 

यहाँ एक आईआरबी सत्र है: मैं निम्नलिखित (सरलीकृत) वर्ग के साथ काम एक आवेदन करने के लिए होता है ।रेल कोड इंगित करता है कि यह भी समझ में आता है; new

def create(attributes = nil, &block) 
    if attributes.is_a?(Array) 
    attributes.collect { |attr| create(attr, &block) } 
    else 
    object = new(attributes) 
    yield(object) if block_given? 
    object.save 
    object 
    end 
end 

तो create कॉल और इससे पहले कि यह yield रों object के लिए मूल्य प्रदान करती है: create में। यहाँ new में प्रासंगिक हिस्सा है:

def initialize(attributes = nil) 
    # truncated for space 
    result = yield self if block_given? 
    run_callbacks :initialize 
    result 
end 

आप देख सकते हैं, इससे पहले कि यह रिटर्न new बिना शर्त initialize कॉलबैक कहता है, और इस तरह से पहले create भी ब्लॉक आप पारित करने के लिए पैदावार। जब तक आपका ब्लॉक ऑब्जेक्ट प्राप्त करता है, after_initialize विधि पहले से ही निष्पादित कर चुकी है।

डबल चेक करें कि (1) रेल का आपका संस्करण अद्यतित है (3.0.5 अब तक मेरा मानना ​​है) और वह (2) कुछ भी baz को बिना किसी एहसास के सेट कर रहा है।

+1

साझा करने के लिए धन्यवाद बोल्ड में टुकड़े के लिए धन्यवाद। यही वही था जो मेरी समस्याओं का कारण बन रहा था। मैंने अपने प्रश्न के निचले भाग में थोड़ा सा स्पष्टीकरण लिखा था कि क्या हो रहा था। सहायता के लिए धन्यवाद। – HMCFletch

+0

बहुत रोचक, और बढ़िया है कि आप क्या चल रहा था नीचे खींचा। मैं कल्पना नहीं कर सकता कि आप अकेले ही इस व्यक्ति द्वारा काट रहे हैं ... –

संबंधित मुद्दे

 संबंधित मुद्दे