रेल 3 में लिबर फोल्डर से मॉड्यूल / क्लास लोड करने का सबसे अच्छा तरीका?


273

चूँकि नवीनतम रेल 3 रिलीज़ ऑटो-लोडिंग मॉड्यूल और कक्षाओं से लीबी नहीं है, इसलिए उन्हें लोड करने का सबसे अच्छा तरीका क्या होगा?

गीथूब से:

A few changes were done in this commit:

Do not autoload code in *lib* for applications (now you need to explicitly 
require them). This makes an application behave closer to an engine 
(code in lib is still autoloaded for plugins);

जवाबों:


250

रेल 2.3.2 के रूप में , एक सेटिंग config/application.rbहै जिसमें आप उन निर्देशिकाओं को निर्दिष्ट कर सकते हैं जिनमें वे फाइलें हैं जो आपको ऑटोलोडेड चाहिए।

Application.rb से:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)

7
नोट आभारी के @ भी जवाब देने के आप के पूरे सबट्री AutoLoad करने के लिए देख रहे हैं app/lib
टॉम हैरिसन

199
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

स्रोत: रेल 3 क्विकटिप: सभी उपनिर्देशिकाओं सहित ऑटोलोड की कार्यकारी निर्देशिका, आलसी लोडिंग से बचें

कृपया ध्यान रखें कि सर्वर शुरू होने पर केवल काम के फ़ोल्डर में निहित फाइलें लोड की जाती हैं। यदि आप उन फ़ाइलों को ऑटोरेलोड के लिए आराम चाहते हैं, तो पढ़ें: रेल 3 क्विकटिप: विकास मोड में ऑटो फ़ोल्डर को पुनः लोड करें । ज्ञात हो कि यह उत्पादन वातावरण के लिए नहीं है क्योंकि स्थायी पुनः लोड मशीन को धीमा कर देता है।


लिंक मर चुके हैं
Besi

84

ऑटोलोडिंग सामान का जादू

मुझे लगता है कि उन फ़ोल्डरों को नियंत्रित करने का विकल्प जिसमें से ऑटोलेडिंग सामान हो जाता है, को अन्य उत्तरों में पर्याप्त रूप से कवर किया गया है। हालाँकि, यदि किसी अन्य व्यक्ति को मुसीबत में सामान रखने में कठिनाई हो रही है, जबकि उनके ऑटोलैड पथ को आवश्यकतानुसार संशोधित किया गया है, तो यह उत्तर यह समझाने की कोशिश करता है कि इस ऑटोलॉड चीज़ के पीछे क्या जादू है।

इसलिए जब उपनिर्देशिका से सामान लोड करने की बात आती है तो एक गोच या एक सम्मेलन होता है जिसे आपको पता होना चाहिए। कभी-कभी रूबी / रेल्स का जादू (इस बार ज्यादातर रेल्स) यह समझने में मुश्किल कर सकता है कि कुछ क्यों हो रहा है। ऑटोलोड पथों में घोषित कोई भी मॉड्यूल केवल तभी लोड किया जाएगा जब मॉड्यूल नाम मूल निर्देशिका नाम से मेल खाता हो। तो मामले में आप lib/my_stuff/bar.rbकुछ इस तरह की कोशिश करते हैं:

module Foo
  class Bar
  end
end

इसे स्वचालित रूप से लोड नहीं किया जाएगा। फिर अगर आप माता-पिता का नाम बदलकर fooइस प्रकार अपने मॉड्यूल को पथ पर होस्ट कर रहे हैं lib/foo/bar.rb:। यह तुम्हारे लिए वहाँ होगा। एक अन्य विकल्प उस फ़ाइल का नाम है जिसे आप मॉड्यूल नाम से ऑटोलॉइड चाहते हैं। जाहिर है कि उस नाम से केवल एक फ़ाइल हो सकती है। मामले में आपको अपने सामान को कई फाइलों में विभाजित करने की आवश्यकता होती है जो आप निश्चित रूप से उस एक फाइल का उपयोग कर सकते हैं जो अन्य फ़ाइलों की आवश्यकता होती है, लेकिन मैं इसकी सिफारिश नहीं करता हूं, क्योंकि तब जब विकास मोड पर होता है और आप उन अन्य फाइलों को संशोधित करते हैं तो रेल स्वचालित रूप से असमर्थ है उन्हें आपके लिए पुनः लोड करें। लेकिन अगर आप वास्तव में चाहते हैं कि आपके पास मॉड्यूल नाम से एक फ़ाइल हो सकती है जो तब मॉड्यूल का उपयोग करने के लिए आवश्यक वास्तविक फ़ाइलों को निर्दिष्ट करता है। तो आपके पास दो फाइलें हो सकती हैं: lib/my_stuff/bar.rbऔर lib/my_stuff/foo.rbपूर्व ऊपर की तरह ही हो और बाद वाली एक ही लाइन से युक्त हो:require "bar"और बस वही काम करेगा।

पुनश्च मैं एक और महत्वपूर्ण बात जोड़ने के लिए मजबूर महसूस करता हूं। हाल ही में, जब भी मैं चाहता हूं कि लिबरलडेज प्राप्त करने के लिए आवश्यक निर्देशिका में कुछ हो, तो मैं यह सोचना शुरू कर देता हूं कि अगर यह कुछ ऐसा है जो मैं वास्तव में इस परियोजना के लिए विशेष रूप से विकसित कर रहा हूं (जो आमतौर पर है, तो यह किसी दिन हो सकता है कई परियोजनाओं में उपयोग किए गए कोड के "स्थिर" स्निपेट में बदल दें या एक गिट सबमॉड्यूल, आदि .. जिस स्थिति में यह निश्चित रूप से काम करने योग्य फ़ोल्डर में होना चाहिए) तो शायद इसका स्थान पूरी तरह से lib फ़ोल्डर में नहीं है। शायद यह ऐप फ़ोल्डर के तहत एक सबफ़ोल्डर में होना चाहिए · मुझे यह महसूस होता है कि यह चीजों को करने का नया तरीका है। जाहिर है, एक ही जादू काम में है जहाँ भी आप ऑटोलैड पथ में अपना सामान डालते हैं तो यह इन चीजों के लिए अच्छा है। वैसे भी, इस विषय पर सिर्फ मेरे विचार हैं। आप असहमत होने के लिए स्वतंत्र हैं। :)


अद्यतन: जादू के प्रकार के बारे में ..

जैसा कि गंभीर ने अपनी टिप्पणी में कहा, कोर "ऑटोलॉड एक मॉड्यूल तंत्र" निश्चित रूप से रूबी का हिस्सा है, लेकिन ऑटोलॉड पथ सामान नहीं है। आपको करने के लिए रेल की आवश्यकता नहीं हैautoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar")। और जब आप पहली बार मॉड्यूल फू को संदर्भित करने की कोशिश करेंगे तो यह आपके लिए लोड होगा। हालाँकि रेल क्या करती है, यह हमें पंजीकृत फ़ोल्डरों से स्वचालित रूप से सामान को लोड करने और लोड करने का एक तरीका देता है और इसे इस तरह से लागू किया गया है कि इसे नामकरण सम्मेलनों के बारे में कुछ ग्रहण करना होगा। यदि यह उस तरह से लागू नहीं किया गया था, तो हर बार जब आप किसी ऐसी चीज का संदर्भ देते हैं जो वर्तमान में लोड नहीं होती है तो उसे सभी ऑटोलैड फ़ोल्डरों में सभी फाइलों से गुजरना होगा और जांचना होगा कि उनमें से किसी में क्या आप संदर्भ के लिए प्रयास कर रहे हैं। यह बदले में ऑटोलिंग और ऑटोरेलोइंग के विचार को हरा देगा। हालाँकि, इन सम्मेलनों के साथ यह मॉड्यूल / वर्ग को आपके लोड करने की कोशिश में कटौती कर सकता है जहां इसे परिभाषित किया जा सकता है और बस इसे लोड किया जा सकता है।


1
यह रूबी जादू क्यों है? रूबी सिर्फ मॉड्यूल # ऑटोलॉड फ़ंक्शन प्रदान करता है जिसका उपयोग आप एक (अपरिभाषित) स्थिरांक तक पहुँचने के दौरान लोड की जा रही फ़ाइल को कमांड करने के लिए कर सकते हैं (देखें ruby-doc.org/core-1.9.3/Module.html#method-autoload )। निर्देशिकाओं / फ़ाइलों के लिए मॉड्यूल / वर्ग के नाम का मिलान मेरे विचार से Rails / ActiveSupport (जैसे यहाँ: github.com/rails/rails/blob/… ) में किया गया है। क्या मै गलत हु?
प्रात:

हां, मेरा मानना ​​है कि आप सही हैं। मैं अपने मूल उत्तर को "सही" करने के लिए बहुत जल्दबाजी में था जब ज़ब्बा ने अपना "दोष" बताया। मुझे इस मुद्दे को स्पष्ट करने के लिए अपने उत्तर को थोड़ा और अपडेट करने दें।
तिमो

1
मैंने आधे घंटे का समय बिताया। मुझे ऑटोलैड Sprockets :: JSRender :: प्रोसेसर की आवश्यकता (चाहिए) थी। इसके लिए रास्ता रेल कंसोल में उतरकर और "Sprockets :: JSRender :: Processor" .underscore और डिसओवर करते हुए पाया जा सकता है कि यह "sprockets / js_render / processor" (.rb जोड़ा गया) HTH किसी के साथ है।
पेडज

आपने सिर्फ मेरी पवित्रता को बचाया। ~ राहत की गहरी आह ~ बांटने के लिए बहुत बहुत धन्यवाद :)
ब्रेंडेन

इस सबसे उपयोगी टिप्पणी के लिए धन्यवाद। मुझे समझ नहीं आया कि कुछ मॉड्यूल ऐसा व्यवहार क्यों कर रहे थे जब तक मैंने आपकी टिप्पणी नहीं पढ़ी। आप पर आशीर्वाद!
mjnissim

41

चेतावनी: यदि आप अपने 'लिबास' फोल्डर से 'मंकी पैच' या 'ओपन क्लास' को लोड करना चाहते हैं, तो 'ऑटोलॉड' दृष्टिकोण का उपयोग न करें !!!

  • " config.autoload_paths " दृष्टिकोण: केवल तभी काम करता है जब आप एक वर्ग को लोड कर रहे हों जो केवल एक ही स्थान पर परिभाषित हो। यदि कुछ वर्ग पहले से ही कहीं और परिभाषित किया गया है, तो आप इसे इस दृष्टिकोण से दोबारा लोड नहीं कर सकते।

  • " config / initializer / load_rb_file.rb " दृष्टिकोण: हमेशा काम करता है! जो भी लक्ष्य वर्ग एक नया वर्ग या "खुला वर्ग" या मौजूदा वर्ग के लिए "बंदर पैच" है, वह हमेशा काम करता है!

अधिक जानकारी के लिए, देखें: https://stackoverflow.com/a/6797707/445908


6
यह समझने के लिए एक महत्वपूर्ण अंतर है। इसके लिए धन्यवाद।
टायलर कोलियर


18

मेरे मामले में मैं बस एक फ़ाइल को सीधे काम के तहत लोड करने की कोशिश कर रहा था।

Application.rb के भीतर ...

require '/lib/this_file.rb' 

काम नहीं कर रहा था, यहां तक ​​कि सांत्वना में भी और फिर जब मैंने कोशिश की

require './lib/this_file.rb' 

और रेल पूरी तरह से फ़ाइल लोड करता है।

मैं अभी भी बहुत सुंदर हूं और मुझे यकीन नहीं है कि यह क्यों काम करता है लेकिन यह काम करता है। अगर कोई इसे मुझे समझाना चाहेगा तो मैं इसकी सराहना करूंगा: आशा करता हूं कि इससे किसी को भी मदद मिलेगी।


2
ऐसा इसलिए है क्योंकि/lib/this_file.rb वर्तमान निर्देशिका (रेल कंसोल में, जो आपकी रेल रूट होगी) में दिखता है, और /lib/this_file.rb एक निरपेक्ष पथ के रूप में दिखता है। उदाहरण: ./lib/this_file.rb = /var/www/myrailsapp/lib/this_file.rb, /lib/this_file.rb = /lib/this_file.rb
जेसन

7

मुझे भी यही समस्या थी। यहाँ है कि मैं इसे कैसे हल किया। समाधान कामेच्छा निर्देशिका और सभी उपनिर्देशिकाओं (न केवल प्रत्यक्ष) को लोड करता है। बेशक आप सभी निर्देशिकाओं के लिए इसका उपयोग कर सकते हैं।

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

5
यह पूरी तरह से clobbering रेल नामकरण सम्मेलनों के बुरा पक्ष प्रभाव है। यदि lib / bar / foo.rb को परिभाषित करना बार :: Foo lib / foo.rb को परिभाषित करने से पहले दिखाई देता है, तो autoload लुकअप में Foo को परिभाषित करता है, तो आपको भ्रमित करने वाली त्रुटियां मिलेंगी जैसे Expected lib/bar/foo.rb to define constant Fooयदि आप Foo के संदर्भ में lib / foo.rb को लोड करने का प्रयास करते हैं। स्थिर।
जैकब

5

config.autoload_paths मेरे लिए काम नहीं करता है। मैं इसे दूसरे तरीके से हल करता हूं

3 पटरियों पर रूबी / स्वचालित फ़ोल्डर से स्वचालित पुनः लोड (ऑटोलॉड) कोड न करें। मैं अंदर डालकर इसे हल करता हूंApplicationController

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 

4

यदि केवल कुछ फ़ाइलों को ही लीबी में मॉड्यूल तक पहुंच की आवश्यकता होती है, तो बस उन फ़ाइलों के लिए एक आवश्यक विवरण जोड़ें, जिनकी आवश्यकता है। उदाहरण के लिए, यदि एक मॉडल को एक मॉड्यूल तक पहुंचने की आवश्यकता है, तो जोड़ें:

require 'mymodule'

model.rb फ़ाइल के शीर्ष पर।


50
आपको requireरेल एप्लिकेशन के भीतर उपयोग नहीं करना चाहिए , क्योंकि यह ActiveSupport::Dependenciesउस कोड को [ठीक से] लोड करने से रोकता है। इसके बजाय आपको config.autoload_pathsऊपर दिए गए उत्तर की तरह उपयोग करना चाहिए , और फिर आवश्यकतानुसार शामिल / विस्तारित करना चाहिए।
ben_h

13
शुक्रिया @ मायके, मैं वही करने जा रहा था जो आपने किया था, इसका स्पष्टीकरण देखना अच्छा था कि यह बुरा क्यों है, उत्तर न हटाने के लिए धन्यवाद।
पोपीनो

यदि आप केवल एक मॉड्यूल लोड करना चाहते हैं तो 'मायमॉड्यूल' के बारे में क्या शामिल है?
माइक

1
@ben_h क्या आपको requireकिसी Rails ऐप में कहीं से भी नहीं आना चाहिए ? एक रेक कार्य में, मैं वर्तमान में require-ing और include-ing एक मॉड्यूल जो में रहता है lib/। क्या मुझे ऐसा नहीं करना चाहिए?
डेनिस

@ben_h मेरी खोज बताती है कि यह requireआपके lib/कोड के लिए सामान्य है (जैसे यह ब्लॉग पोस्ट , यह SO उत्तर )। मैं अभी भी पूरी बात को लेकर अनिश्चित हूं। क्या आप उपयोग नहीं करने के दावे के पीछे अधिक प्रमाण दे सकते हैं require?
डेनिस

2

फ़ाइल नाम को सही ढंग से वर्तनी।

गंभीरता से। मैंने एक घंटे के लिए एक क्लास के साथ लड़ाई की क्योंकि क्लास गवर्नेंस थी :: आर्किटेक्चरबोर्ड और फाइल लिब / गवर्नेंस / आर्किटेक्चर_बॉर्ड.बीआर ("बोर्ड" में O और A ट्रांसपोज्ड थी)

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


2

के रूप में Rails 5, यह के रूप में फ़ोल्डर के लिए एप्लिकेशन निर्देशिका के अंतर्गत lib फ़ोल्डर डाल या बजाय बनाने के अन्य सार्थक नाम रिक्त स्थान की सिफारिश की है services, presenters,features आदि और रेल द्वारा स्वत: लोड करने के लिए एप्लिकेशन निर्देशिका के अंतर्गत डाल दिया।

कृपया इस GitHub चर्चा लिंक को भी देखें।


1

ऐसे कई कारण हैं जिनकी वजह से आपको काम करने में समस्या हो सकती है - समस्या के लिए यहाँ देखें - http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

  • ऑटोलोड पथ को ठीक करें
  • थ्रेडसेफ़ संबंधित
  • नामकरण संबंधी
  • ...
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.