2011-01-16 16 views
10
  • रेल: 3.0.3
  • रूबी: 1.9.2

YAML.load या Marshal.load का उपयोग कर एक बहुत ही सरल वस्तु deserialize की कोशिश कर रहा एक भ्रष्ट पैदा करता है ऑब्जेक्ट क्योंकि वर्ग जो deserializing प्रक्रिया पर आवश्यक नहीं है।रेल YAML/मार्शल deserializing पर कक्षाओं लोड नहीं करता है वस्तुओं

उदाहरण:

# app/models/my_model.rb 
class MyModel 
    attr_accessor :id 
end 

# test/unit/serializing_test.rb 
require 'test_helper' 

class SerializingTest < Test::Unit::TestCase 
    def test_yaml_serialize_structure 
    my_model = MyModel.new 
    my_model.id = 'my model' 

    File.open("#{Rails.root}/tmp/object.yml" , 'w') do |f| 
     YAML::dump(my_model, f) 
    end 
    end 

    def test_yaml_deserialize_structure 
    object = YAML.load_file "#{Rails.root}/tmp/object.yml" 
    assert(object.instance_of? MyModel) 
    assert_equal('my model', object.id) 
    end 
end 
इस कोड को हम किसी भी त्रुटि के बिना इस खोल कंसोल सत्र चला सकते हैं के साथ

:

$ ruby -Itest test/unit/serializing_test.rb -n test_yaml_serialize_structure 
$ ruby -Itest test/unit/serializing_test.rb -n test_yaml_deserialize_structure 

लेकिन अगर मैं अक्रमांकन एक रेल से कॉल सांत्वना वस्तु है चलाने उचित रूप से deserialized नहीं है क्योंकि कक्षा कभी आवश्यक नहीं है:

$ rails c 
ruby-1.9.2-p0 > object = YAML.load_file "#{Rails.root}/tmp/object.yml" 
=> #<Syck::Object:0x0000010322ea30 @class="MyModel", @ivars={"id"=>"my model"}> 

मैं जानता हूँ कि केवल समस्या यह है कि वर्ग की आवश्यकता नहीं है क्योंकि अगर मैं इसे की आवश्यकता द्वारा हाथ सब कुछ काम करता है:

ruby-1.9.2-p0 > require "#{Rails.root}/app/models/my_model" 
=> ["MyModel"] 
ruby-1.9.2-p0 > object = YAML.load_file "#{Rails.root}/tmp/object.yml" 
=> #<MyModel:0x0000010320c8e0 @id="my model"> 

मैं केवल YAML उदाहरण प्रस्तुत किया है लेकिन मार्शल के साथ बहुत ही है।

यह भी कहना है कि हालांकि मैं में समस्या का पुन: उत्पन्न कर रहा हूं हालांकि रेल कंसोल मूल रूप से यह समस्या मुझे मेरे आवेदन के सामान्य अनुरोध में पागल कर रही थी।

तो सवाल यह है कि: मैं रेल में वस्तुओं को deserialize कैसे कर सकते हैं बिना मेरे सभी वर्गों को हाथ से आवश्यकता है?

धन्यवाद

च।

+0

मैं सिर्फ एहसास हो गया है कि एक ** विकास के वातावरण में यह केवल happend **। – fguillen

+1

मैं देख रहा हूं कि अगर मैं सक्रिय 'config.cache_classes' को deserialization अच्छी तरह से काम करता है, लेकिन निश्चित रूप से: ** मैंने क्लास ऑटो रीफ्रेशिंग ** खो दिया है:/ – fguillen

उत्तर

20

ठीक है, के बाद @tadman और जवाब मैं स्पेनिश ROR मेलिंग सूची में प्राप्त हुआ है के एक समूह को पढ़ [1] मैं कुछ गर्म युक्तियाँ एकत्र किया आप रूबी deserializing और रेल में वर्ग लोड हो रहा है के साथ सौदा है जब:

अपने development.rb में सुपर तेजी से समाधान

उपयोग config.cache_classes = true लेकिन आप वर्ग स्वतः रीफ़्रेश खो दिया जाएगा।

बेहतर समाधान

सभी वर्गों कि वाला deserialized लेकिन जा रहे हैं की आवश्यकता होती है नहीं के साथ require लेकिन साथ require_dependency [2] तो विकास वातावरण में कक्षा ऑटो ताज़ा काम कर ही रहेगा।

सुरुचिपूर्ण समाधान

बंदर-पैच YAML और मार्शल मणि require_dependency कॉल करने के लिए जब वे एक गैर परिभाषित वर्ग deserialize करने के लिए उन्हें बताना।

और @Xavi मुझे बंदर-पैच Marshal (वह कहता है कि वह हवा पर यह लिखा था और यह इतना परीक्षण नहीं किया गया है अपने स्वयं के जोखिम में इसका इस्तेमाल करते हैं) [3]

+0

यह उत्तर एक लाइफसेवर है। सोचा था कि मुझे अपने वास्तुकला पर पुनर्विचार करना होगा ... – fivetwentysix

+0

धन्यवाद! वास्तव में मुझे क्या चाहिए! हालांकि, मैं सुझाव # 2 में 'आवश्यक' क्या कर रहा हूं, इस बारे में थोड़ा उलझन में हूं। –

+0

एफवाईआई, @ फ़ुगुलीन मेरे पास वापस आ गए और यहां कुछ समाधान दिए गए हैं: '* कस्टम स्टार्टिस्टाइज़र में: '/config/initializers/explicit_requires.rb' * '/config/application.rb' के नीचे ' –

0

जहां तक ​​मुझे पता है, वाईएएमएल और मार्शल दोनों रेल ऑटोलोडर का उपयोग नहीं करते हैं। आपको आगे बढ़ना होगा और किसी भी कक्षा को प्री-लोड करना होगा जिसे deserialized करने की आवश्यकता हो सकती है।

यह थोड़ा सा है, खासकर विकास वातावरण में जहां लगभग कुछ भी आवश्यक नहीं है, इससे पहले लोड किया जाता है।

2

स्वचालित रूप से ढंग @fguillen पता चलता है में YAML लोड हो रहा है पर कक्षाएं आवश्यक बनाने के लिए सुंदर है, मैं इस छोटे से बंदर-पैच लिखा था।

यह कक्षाओं को हल करने के लिए साइको टॉर्बी क्लास के किसी भी वर्ग की आवश्यकता पर निर्भर करता है।

एक धारावाहिक सक्रिय रिकॉर्ड में मेरे लिए काम करता है जो कस्टम क्लास इंस्टेंस, वाईएमएमवी स्टोर करता है।

module Psych::Visitors 
    ToRuby.class_eval do 
    alias :resolve_class_without_autoload :resolve_class 
    def resolve_class klassname 
     begin 
     require_dependency klassname.underscore 
     rescue NameError, LoadError 
     end 
     resolve_class_without_autoload klassname 
    end 
    end 
end 
0

मैं यह काम (रेल 5.0.2 का प्रयोग करके) बनाने के लिए @ बेन-पैटरसन का जवाब थोड़ा अनुकूल करने के लिए किया था:

module Psych::Visitors 
    ToRuby.class_eval do 
     def resolve_class(klassname) 
      begin 
       class_loader.load klassname 
      rescue ArgumentError 
       require_dependency klassname.underscore 
       klassname.constantize 
      end 
     end 
    end 
end