2011-08-16 15 views
24

हमने अभी 'lib' में एक नई फ़ाइल बनाई है जिसने लोड त्रुटियों से जुड़े सिरदर्द की श्रृंखला बनाई है।असंगत "लोडरर" व्यवहार 'lib' नेमस्पेसिंग/ऑटोलोडिंग के साथ व्यवहार

/lib/response_set.rb:

module MyCompany 
    class ResponseSet < Array 
    ... 
    end 
end 

/spec/lib/response_set_spec.rb

require 'spec_helper' 

describe MyCompany::ResponseSet do 
    describe "..." do 
    ... 
    end 
end 

Rspec में यह कल्पना चल रहा है हमें निम्नलिखित त्रुटि देता है जब वह पहली बार के लिए हो जाता है ' वर्णन करें:

/Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:492:in `load_missing_constant': Expected /Users/my_stuff/projects/my_project/lib/response_set.rb to define ResponseSet (LoadError) 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:183:in `block in const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `each' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/backward_compatibility.rb:20:in `const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-expectations-2.5.0/lib/rspec/expectations/backward_compatibility.rb:6:in `const_missing' 
    from /Users/my_stuff/projects/my_project/spec/lib/response_set_spec.rb:4:in `<top (required)>' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in `load' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in `block in load_spec_files' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in `map' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in `load_spec_files' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/command_line.rb:18:in `run' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:55:in `run_in_process' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:46:in `run' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:10:in `block in autorun' 

हाउवर! हम कई अन्य फाइलों का उपयोग लंबे समय तक कर रहे हैं जिनकी समान संरचना है।

/lib/smart_set.rb

module MyCompany 
    class SmartSet < Array 
    ... 
    end 
end 

और /spec/lib/smart_set_spec.rb

require 'spec_helper' 

describe MyCompany::SmartSet do 
    describe "..." do 
    ... 
    end 
end 

यह: उदाहरण के लिए, यहाँ एक और एक है कि ठीक काम कर रहा है, क्योंकि यह बनाया गया था है फ़ाइल में समान संरचना है लेकिन कोई समस्या नहीं है।

ResponseSet (समस्या वर्ग) स्पष्ट रूप से किसी भी कारण के कारण मुद्दों को लोड नहीं कर रहा है। रेल कंसोल में, पहली बार मैं एक बनाने के लिए प्रयास करते हैं, मैं कोई त्रुटि मिलती है, लेकिन फिर मैं एक बाद में बना सकते हैं:

Loading development environment (Rails 3.0.4) 
ruby-1.9.2-p136 :001 > rs = MyCompany::ResponseSet.new 
LoadError: Expected /Users/my_stuff/projects/my_project/lib/response_set.rb to define ResponseSet 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:492:in `load_missing_constant' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:183:in `block in const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `each' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:503:in `load_missing_constant' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:183:in `block in const_missing' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `each' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `const_missing' 
    from (irb):1 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/railties-3.0.4/lib/rails/commands/console.rb:44:in `start' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/railties-3.0.4/lib/rails/commands/console.rb:8:in `start' 
    from /Users/my_stuff/.rvm/gems/[email protected]_project/gems/railties-3.0.4/lib/rails/commands.rb:23:in `<top (required)>' 
    from script/rails:6:in `require' 
    from script/rails:6:in `<main>' 
ruby-1.9.2-p136 :002 > rs = MyCompany::ResponseSet.new 
=> [] 

इसके अलावा, response_set_spec के शीर्ष पर

require 'response_set' 

जोड़ने। आरबी उन परीक्षणों को चलाने की अनुमति देता है। लेकिन smart_set_spec.rb के लिए ऐसी कोई चीज़ जरूरी नहीं है।

निम्नलिखित application.rb में जगह में है:

config.autoload_paths += %W(#{config.root}/lib) 
config.autoload_paths += Dir["#{config.root}/lib/**/"] 
config.autoload_paths += Dir["#{config.root}/app/models/**/"] 

अब, मैं समझता हूँ कि रेल कैसे फ़ाइल संरचना चीजों के इन प्रकार के लिए नाम स्थान संरचना से मेल खाना चाहिए पर राय के कुछ प्रकार है, और हम पुनर्गठित किया है इस अंत में हमारे मॉड्यूल और फाइलें। यह समस्या को हल करने के लिए लगता है (हालांकि हम थोड़ी देर के लिए कुछ और अजीब लोड त्रुटियों को देख रहे थे जब हमने पूर्ण परीक्षण सूट चलाया - ये रहस्यमय तरीके से चले गए हैं)। फिर भी यहां हर कोई परेशान है और थोड़ा नाराज नहीं है कि रेल इतनी असंगत है और हम जानना चाहते हैं कि क्यों। जैसा कि आप देख सकते हैं कि दो फाइलें हैं जो नामस्थान और फ़ाइल संरचना के समान हैं, पूरी तरह से अलग तरीके से इलाज किया जा रहा है। असल में हमारे पास 'lib' के शीर्ष स्तर में लगभग दर्जन अन्य फाइलें हैं जो समान नामस्थान के साथ हैं जो कभी भी किसी भी समस्या का कारण नहीं बनती हैं। क्या कोई यह बता सकता है कि बिल्ली यहाँ क्या चल रहा है?

उत्तर

4

मैं रेल स्रोत में देखा और वहाँ load_missing_constant विधि में एक

if file_path && ! loaded.include?(File.expand_path(file_path)) # We found a matching file to load 
    require_or_load file_path 
    raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless local_const_defined?(from_mod, const_name) 
    return from_mod.const_get(const_name) 
elsif ... 

खंड है। मुझे लगता है कि require_or_load को raise से पहले बुलाया गया है, यह एक कारण हो सकता है कि आपके उदाहरण में दूसरी कॉल पर कोई त्रुटि नहीं है ...

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

पीएस मैंने यहां एक समान प्रश्न सबमिट किया है: http://www.ruby-forum.com/topic/2376956

+0

धन्यवाद Alexey। यह संदिग्ध लग रहा है। ऐसा लगता है कि अपवाद को उठाना मौसम 'requ_or_load' पर निर्भर होना चाहिए सफल रहा। लेकिन फिर मैं भूलभुलैया से बहुत परिचित नहीं हूं कि रेल गड़बड़ है। –

+0

@ निक, स्पष्ट रूप से अपवाद उठाया जाता है, जब फ़ाइल लोड करने के बाद, निरंतर अभी भी परिभाषित नहीं किया जाता है। आपके मामले में, ऐसा लगता है कि फ़ाइल 'ResponseSet' को परिभाषित करने की अपेक्षा की जाती है, जबकि यह' MyCompany :: ResponseSet' को परिभाषित करता है (इस तरह यह मुझे देखता है, लेकिन मैं एक विशेषज्ञ नहीं हूं)। असंगतता सबसे अजीब बात है। क्या आप सुनिश्चित हैं कि आपने मूल समस्या को सरल नहीं बनाया है? हो सकता है कि 'MyCompany :: SmartSet' '/ lib/my_company/smart_set.rb' में है और न केवल'/lib/smart_set.rb' है? मैंने एक समान मुद्दे के बारे में [गिटहब पर एक बग रिपोर्ट] सबमिट की है (https://github.com/rails/rails/issues/2572)। – Alexey

+0

नहीं। फाइल संरचनाएं समान थीं। हमने कुछ संभावित अंतरों की जांच करने में कुछ घंटे बिताए जिन्हें हम सोच सकते थे। प्रत्येक वर्ग (यानी गुण और विधियों) के वास्तविक कार्यान्वयन के साथ केवल अंतर ही हैं, लेकिन इनमें से कोई भी इस बात को प्रभावित नहीं करेगा कि फ़ाइलों को कैसे लोड किया जाता है! –

27

हमारे पास एक समान समस्या थी, जो खोदने के बाद, रेल 3.x और autoload_paths में परिवर्तनों के कारण हुई।

हमारा मामला केवल परीक्षण में दिखाई दिया (RAILS_ENV=test)। जब रेल नियंत्रकों को लोड कर रहा था, तो यह प्रत्येक नियंत्रक के मिलान मॉडल (एक एक्शनकंट्रोलर :: बेस.वाप_परमीटर एक प्रारंभकर्ता में सेट) के कारण देखने के लिए scrambled। आखिरकार यह उपर्युक्त विधि (load_missing_constant) तक घायल हो गया। चूंकि हमारे autoload_paths में lib और lib/** दोनों शामिल हैं, इसलिए लीग के तहत सभी उपनिर्देशिकाओं से सभी फ़ाइलों में रेल खींच लिया गया है। दुर्भाग्यवश, उपनिर्देशिका से लोड करते समय यह निहित नामस्थान को अनदेखा करता प्रतीत होता है। यह Base बनाम Foo::Base परिभाषित करने के लिए foo/base.rb की अपेक्षा की गई थी। ऐसा लगता है कि मूल दोष: load_missing_constantsearch_for_file को आमंत्रित करता है जो किसी भी फ़ाइल को लौटाता है जिसका नाम मेल खाता है (उदाहरण के लिए, मेरे उदाहरण में, foo/base.rb को आधार.आरबी से मेल खाता था)।

यह कहना मुश्किल है कि यह रेल में एक त्रुटि है - जिसमें यह रुबी द्वारा धारित नाम-से-निर्देशिका मैपिंग का उल्लंघन करता है - या autoload_paths का दुरुपयोग।

हमने lib/** को autoload_paths से हटाकर और application.rb पर जरूरी आवश्यक विवरण जोड़कर अब इसके लिए काम किया है।

+2

मुझे एक ही चीज़ थी। मुझे लगता है कि आप रूट समस्या के बारे में सही रास्ते पर हैं .... आश्चर्य है कि कोई और इसके बारे में शिकायत नहीं कर रहा है। –

+8

रेल मुझे परेशान करना शुरू कर रहा है। – Zabba

+0

@Zabba: हाँ, एक सीधे जैकेट में बदल रहा प्रतीत होता है। –

4

ब्रेंडन द्वारा सही दिशा में इंगित किया गया था, अपने autoload_paths की जांच करें। मैं एक ऐसी ही त्रुटि थी और इस application.rb में मेरे लिए अपराधी था: एक बार मैं एक उप-निर्देशिका होने के साथ-साथ मॉडल के लिए मॉड्यूल का उपयोग शुरू किया

config.autoload_paths += Dir["#{Rails.root}/app/models/[a-z]*"] 

मेरा ऐप खुश नहीं था। मैं autoload को मेरा बदला सिर्फ गैर मॉड्यूल निर्देशिका:

config.autoload_paths += Dir["#{Rails.root}/app/models/aaaaaaaaa"] 
config.autoload_paths += Dir["#{Rails.root}/app/models/bbbbbbbbb"] 
1

मैं साथ namespaced वर्गों को गलत तरीके से किया जा रहा autoloaded बहुत ही समस्या का सामना करना पड़ा है। यह (ब्रेंडन के जवाब से) इसे हल करने सुराग है:

चूंकि हमारे autoload_paths दोनों लिब और lib/**, रेल lib के तहत सभी सबडायरेक्टरियों से सभी फाइलों में खींच लिया शामिल थे। दुर्भाग्यवश, उपनिर्देशिका से लोड करते समय यह निहित नामस्थान को अनदेखा करता प्रतीत होता है। यह बेस बनाम फू :: बेस परिभाषित करने के लिए foo/base.rb की अपेक्षा की जाती है। यह मूल दोष प्रतीत होता है: load_missing_constant search_for_file को आमंत्रित करता है जो किसी भी फ़ाइल को लौटाता है जिसका नाम मेल खाता है (उदाहरण के लिए, मेरे उदाहरण में, foo/base.rb को आधार.आरबी से मिलान किया गया था)।

और मैं यह app/components/events/* में मेरे सारे namespaced कक्षाएं, Events::Something नाम है, चलती है और निम्नलिखित सामग्री के साथ एक फ़ाइल app/components/events.rb बनाने के द्वारा हल किया है:

%w(file1 file2 ...).each do |file| 
    require "events/#{file}" 
end 

और जब यह एक छोटा सा मैनुअल है, यह एप्लिकेशन, कंसोल और परीक्षण मोड दोनों के लिए काम करता है।

0

नोटिस के लिए एक अन्य बिंदु यह है कि क्या आपके पास सेवा फ़ोल्डर में सही पथ है या नहीं।

सही पथ करके, मेरा मतलब है

ENGINE_NAME/ऐप्स/सेवाओं/ENGINE_NAME/your_service.rb

मैंने गलती से सेवाओं के अंदर ENGINE_NAME फ़ोल्डर भूल गया है, और इस अजीब व्यवहार मिला है।

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