Rails 5: โหลดไฟล์ lib ในการผลิต


128

ฉันได้อัปเกรดหนึ่งในแอปของฉันจาก Rails 4.2.6 เป็น Rails 5.0.0 อัพเกรดคู่มือกล่าวว่าคุณลักษณะ Autoload ถูกปิดใช้งานในขณะนี้ในการผลิตโดยค่าเริ่มต้น

ตอนนี้ฉันมักจะได้รับข้อผิดพลาดบนเซิร์ฟเวอร์การผลิตของฉันเนื่องจากฉันโหลดไฟล์ lib ทั้งหมดด้วย autoload ในapplication.rbไฟล์

module MyApp
    class Application < Rails::Application
        config.autoload_paths += %W( lib/ )
    end
end

สำหรับตอนนี้ผมได้ตั้งconfig.enable_dependency_loadingไปtrueแต่ผมสงสัยว่ามีทางออกที่ดีกว่านี้ ต้องมีเหตุผลที่ทำให้การโหลดอัตโนมัติถูกปิดใช้งานในการใช้งานจริงโดยค่าเริ่มต้น


บ้ามากและเอกสารยังบอกให้คุณทำ auto_load ฉันสับสนมากว่าเกิดอะไรขึ้นในการผลิตสำหรับแอปใหม่ และตั้งแต่ฉันเริ่มเรียนรู้กับ Rails 5 ฉันไม่ได้อ่านคู่มือการย้ายข้อมูล ฉันยื่นเรื่องเอกสารเพื่อหวังว่าจะได้รับการแก้ไข: github.com/rails/rails/issues/27268
akostadinov

1
น่าแปลกใจที่ฉันมีสองไฟล์ในlibdir ไฟล์หนึ่งสามารถใช้ได้อย่างง่ายดายใน Runtime แต่อีกไฟล์หนึ่งต้องใช้ด้วยตนเอง: D
illusionist

@ โทเบียสคุณจบลงด้วยวิธีใด?
geoboy

@geoboy ฉันรหัสกลุ่ม (เช่นValidators) ในโฟลเดอร์โดยตรงในแอป / ไดเรกทอรีเนื่องจากมีการโหลดรหัสอัตโนมัติ
Tobias

มันเป็นเรื่องของเส้นทางของไฟล์ที่เหมาะสมและการกำหนดระดับนี่คือสิ่งที่ทำงานสำหรับฉันใน Rails 5.2: เส้นทางไฟล์: ความคมชัดระดับ:app/services/paylinx/paylinx_service.rb module Paylinx class PaylinxService end endฉันลองautoload_pathsสิ่งเหล่านี้แล้ว ไม่ได้ผลสำหรับฉัน
NamNamNam

คำตอบ:


161

รายการการเปลี่ยนแปลงของฉันหลังจากย้ายไปที่ Rails 5:

  1. ใส่libdir ลงไปappเพราะโค้ดทั้งหมดในแอพนั้นโหลดอัตโนมัติใน dev และโหลดอย่างกระตือรือร้นในการพัฒนาและที่สำคัญที่สุดคือโหลดอัตโนมัติในการพัฒนาดังนั้นคุณไม่ต้องรีสตาร์ทเซิร์ฟเวอร์ทุกครั้งที่คุณทำการเปลี่ยนแปลง
  2. ลบrequireคำสั่งใด ๆ ที่ชี้ไปที่คลาสของคุณเองข้างในlibเพราะทั้งหมดนั้นมีการโหลดอัตโนมัติอยู่แล้วหากการตั้งชื่อไฟล์ / dir นั้นถูกต้องและหากคุณทิ้งrequireข้อความไว้อาจทำให้การโหลดอัตโนมัติเสียหายได้ ข้อมูลเพิ่มเติมที่นี่
  3. ตั้งค่าconfig.eager_load = trueในทุกสภาพแวดล้อมเพื่อดูปัญหาการโหลดโค้ดอย่างกระตือรือร้นใน dev
  4. ใช้Rails.application.eager_load!ก่อนเล่นกับเธรดเพื่อหลีกเลี่ยงข้อผิดพลาด "การอ้างอิงแบบวงกลม"
  5. หากคุณมีส่วนขยายของทับทิม / รางใด ๆ ให้ปล่อยรหัสนั้นไว้ในlibไดเร็กทอรีเก่าและโหลดด้วยตนเองจาก initializer เพื่อให้แน่ใจว่ามีการโหลดส่วนขยายก่อนที่ตรรกะเพิ่มเติมของคุณจะขึ้นอยู่กับมัน

    # config/initializers/extensions.rb
    Dir["#{Rails.root}/lib/ruby_ext/*.rb"].each { |file| require file }
    Dir["#{Rails.root}/lib/rails_ext/*.rb"].each { |file| require file }
    

8
libตอนนี้ใช้โฟลเดอร์อย่างไร? ฉันหมายถึงการย้ายlibdir ไปที่appdir ดูเหมือนจะเป็นวิธีแก้ปัญหา
Martin Svoboda

3
/app/lib/วางไฟล์ / คลาสและไม่ได้โหลดอัตโนมัติ ทดสอบในราง 5.1 โครงการใหม่
Tim Kretschmer

29
เป็นที่น่าสังเกตว่าคุณต้องหยุดฤดูใบไม้ผลิ ฉันย้ายทุกอย่างไปที่ app / lib / แล้วเสียเวลาเล็กน้อยสงสัยว่าทำไมฉันยังไม่สามารถใช้คลาสจากคอนโซลได้ spring stop ftw :)
jacklin

1
บรรทัดต่อไปนี้จะไปที่ไหนRails.application.eager_load!
Steven Aguilar

1
วิธีนี้อาจใช้ได้ผล แต่ไม่ใช่วิธีแก้ปัญหาที่ดีที่สุด โครงสร้างโฟลเดอร์มีความหมายเช่นกัน สิ่งต่างๆlibมีความใกล้ชิดที่รับรู้ได้แตกต่างจากโครงการในappไดเรกทอรี คำตอบอื่น ๆ หลายคำตอบดีกว่าคำตอบนี้
CWitty

84

ฉันเพิ่งใช้config.eager_load_pathsแทนการconfig.autoload_pathsพูดถึง akostadinov ใน github comment: https://github.com/rails/rails/issues/13142#issuecomment-275492070

# config.autoload_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('lib')

ทำงานเกี่ยวกับการพัฒนาและสภาพแวดล้อมการผลิต

ขอบคุณโจฮานสำหรับข้อเสนอแนะที่จะแทนที่#{Rails.root}/libด้วยRails.root.join('lib')!


3
ใช้งานได้เหมือนมีเสน่ห์ ฉันไม่ชอบไวยากรณ์จึงเปลี่ยนเป็นconfig.eager_load_paths << Rails.root.join('lib').
3limin4t0r

2
สำหรับฉันนั่นคือคำตอบที่ดีที่สุด โครงการของฉันเริ่มบน Rails 5.2 ตั้งแต่เริ่มต้นและโฟลเดอร์ / lib ยังคงถูกสร้างขึ้นนอกโฟลเดอร์ / app ฉันไม่เห็นเหตุผลที่ดีที่จะย้ายมัน
Samir Haddad

1
ใช่มันได้ผล! ดูเหมือนว่า Rails devs สนุกกับการทำให้เกิดปัญหาในการโหลด lib: D จนกว่าจะถึงครั้งต่อไป!
Damien Roche

To Rails 5.2 ใช้config.eager_load_paths += [Rails.root.join('lib')]แทนเพราะ config.eager_load_pathsเป็นอาร์เรย์แช่แข็ง
William Wong Garay

@WilliamWongGaray config.eager_load_paths เป็นแบบอ่านอย่างเดียวเมื่อคุณพยายามแก้ไขใน initializer เมื่อคุณเพิ่มเส้นทางในapplication.rbนั้นจะทำงานโดยใช้ทั้งสองวิธี
Michał Zalewski

31

การโหลดอัตโนมัติถูกปิดใช้งานในสภาพแวดล้อมการผลิตเนื่องจากความปลอดภัยของเธรด ขอขอบคุณ @ Зелёныйสำหรับลิงค์

ฉันจะแก้ไขปัญหานี้โดยการจัดเก็บไฟล์ lib ในlibโฟลเดอร์ของฉันappไดเรกทอรีตามคำแนะนำบนGithub ทุกโฟลเดอร์ในappโฟลเดอร์จะโหลดโดย Rails โดยอัตโนมัติ


6
หากคุณไม่ต้องการอ่านหัวข้อสนทนายาว ๆ ใน Github คุณสามารถค้นหาคำอธิบายที่กลั่นได้ที่นี่: collectiveidea.com/blog/archives/2016/07/22/…
Ernest

7
ฉันใช้config.eager_load_paths << "#{Rails.root}/lib"แล้วนั่นคือ IMO ที่ดีกว่าในการปฏิบัติตามโครงสร้างแอปรางที่แนะนำ
akostadinov

2
app/libแนะนำให้ใส่ lib โดยสมาชิก rail github.com/rails/rails/issues/13142#issuecomment-275549669
eXa

4
สิ่งนี้ทำลายจุดประสงค์ของlibมันอย่างสิ้นเชิง ฉันจะรอให้ tenderlove หรือ DHH ตีระฆังในระหว่างนี้ฉัน (ส่วนตัว) แนะนำให้ใช้คำตอบของ @Lev Lukomsky
Josh Brody

@JoshBrody ความคิดของฉันตอนนี้คือคุณไม่จำเป็นต้องใช้/libไดเร็กทอรีเลย Libs ของบุคคลที่สามเป็นอัญมณีส่วนใหญ่และหากไม่มีควรมีการสร้างอัญมณี สำหรับไฟล์อื่นฉันสร้างโฟลเดอร์เฉพาะใน/appไดเร็กทอรี ตัวอย่างเช่นvalidators.
Tobias

22

ต้องมีเหตุผลที่ทำให้การโหลดอัตโนมัติถูกปิดใช้งานในการใช้งานจริงโดยค่าเริ่มต้น

นี่คือการอภิปรายยาวเกี่ยวกับปัญหานี้ https://github.com/rails/rails/issues/13142


1
การสนทนานี้ดีที่สุดแม้ว่าจะอ่านเป็นเวลานาน แต่ก็เป็นแหล่งข้อมูลเกี่ยวกับเรื่องที่ฉันเจอ
Jason

12

สิ่งนี้อนุญาตให้มี lib autoreload และทำงานในสภาพแวดล้อมการผลิตด้วย

ป.ล. ฉันได้เปลี่ยนคำตอบของฉันแล้วตอนนี้มันเพิ่มทั้งความกระตือรือร้น - เส้นทางการโหลดอัตโนมัติโดยไม่คำนึงถึงสภาพแวดล้อมเพื่อให้สามารถทำงานในสภาพแวดล้อมที่กำหนดเองได้เช่นกัน (เช่นเวที)

# config/initializers/load_lib.rb
...
config.eager_load_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('lib')
...

2
คุณช่วยขยายความได้ไหมว่าเหตุใดจึงแก้ปัญหานี้ได้
Stuart.Sklinar

@ Stuart.Sklinar สิ่งนี้ช่วยให้มี lib autoreload และทำงานในสภาพแวดล้อมการผลิตด้วย ป.ล. ฉันได้เปลี่ยนคำตอบของฉันแล้วตอนนี้มันเพิ่มทั้งความกระตือรือร้น - เส้นทางการโหลดอัตโนมัติโดยไม่คำนึงถึงสภาพแวดล้อมเพื่อให้สามารถทำงานในสภาพแวดล้อมที่กำหนดเองได้เช่นกัน (เช่นเวที)
srghma

1
คุณช่วยขยายความ (ในคำตอบของคุณ) ได้ไหม Code only คำตอบไม่ได้ช่วยให้ทุกคนเข้าใจว่าทำไมจึงควรทำ "แบบนั้น" - ฉันควรเพิ่มฉันไม่ใช่ Ruby dev เพียงแค่ช่วยล้าง SO การเพิ่มความเห็นบางส่วนลงใน "รหัสคำตอบเท่านั้น" จะทำให้ได้บริบทที่แท้จริง
Stuart.Sklinar

1
@ Stuart.Sklinar นั่นเอง
srghma

6

เพียงแค่เปลี่ยนconfig.autoload_pathsเป็นconfig.eager_load_pathsในไฟล์ config / application.rb เนื่องจากในราง 5 การโหลดอัตโนมัติถูกปิดใช้งานสำหรับสภาพแวดล้อมการผลิตโดยค่าเริ่มต้น สำหรับรายละเอียดเพิ่มเติมโปรดปฏิบัติตามการเชื่อมโยง

 #config.autoload_paths << "#{Rails.root}/lib"
  config.eager_load_paths << Rails.root.join('lib')

ใช้ได้กับทั้งการพัฒนาสภาพแวดล้อมและการผลิต


4

ในแง่หนึ่งนี่คือแนวทางที่เป็นหนึ่งเดียวใน Rails 5 เพื่อรวมศูนย์การกำหนดค่าที่กระตือรือร้นและการโหลดอัตโนมัติในขณะเดียวกันก็เพิ่มเส้นทางโหลดอัตโนมัติที่จำเป็นเมื่อใดก็ตามที่มีการกำหนดค่าโหลดที่กระตือรือร้นมิฉะนั้นจะไม่สามารถทำงานได้อย่างถูกต้อง:

# config/application.rb
...
config.paths.add Rails.root.join('lib').to_s, eager_load: true

# as an example of autoload only config
config.paths.add Rails.root.join('domainpack').to_s, autoload: true
...

2

สำหรับใครก็ตามที่ต้องดิ้นรนกับสิ่งนี้เช่นฉันมันไม่เพียงพอที่จะวางไดเรกทอรีไว้app/ข้างใต้ ใช่คุณจะได้รับ autoloading แต่ไม่จำเป็นต้องโหลดที่ต้อง namespacing การประชุมเป็นไปตาม

นอกจากนี้การใช้ initializer สำหรับการโหลดระดับรูทเก่าlibจะป้องกันไม่ให้คุณสมบัติการโหลดซ้ำระหว่างการพัฒนา


0

การย้ายโฟลเดอร์ lib ไปยังแอพช่วยแก้ปัญหา Twitter api ของฉันจะไม่ทำงานในการผลิต ฉันมี "TwitterApi ค่าคงที่ที่ไม่ได้เริ่มต้น" และ Twitter API ของฉันอยู่ในโฟลเดอร์ lib ของฉัน ฉันมีconfig.autoload_paths += Dir["#{Rails.root}/app/lib"]ใน application.rb แต่ใช้งานไม่ได้ก่อนที่จะย้ายโฟลเดอร์

นี่เป็นเคล็ดลับ


-6

เพื่อสรุปคำตอบของ Lev: mv lib appเพียงพอแล้วที่จะมีการlibโหลดโค้ดอัตโนมัติ / โหลดอัตโนมัติทั้งหมดของฉัน

(ราง 6.0.0beta3 แต่ควรทำงานได้ดีบนราง 5.x ด้วย)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.