Câu hỏi Rails 5: Tải các tệp lib trong sản xuất


Tôi đã nâng cấp một trong các ứng dụng của mình từ Rails 4.2.6 lên Rails 5.0.0. Các Hướng dẫn nâng cấp nói rằng, tính năng Tự động tải hiện bị tắt trong sản xuất theo mặc định.

Bây giờ tôi luôn gặp lỗi trên máy chủ sản xuất của mình vì tôi tải tất cả các tệp lib có tự động tải trong application.rb tập tin.

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

Bây giờ, tôi đã đặt config.enable_dependency_loading đến true nhưng tôi tự hỏi nếu có một giải pháp tốt hơn cho điều này. Phải có lý do tính năng Tự động tải được tắt trong sản xuất theo mặc định.


76
2017-07-05 08:30


gốc


Bạn đã bao giờ con số này ra? - dkam
điều điên rồ, và các tài liệu vẫn bảo bạn làm auto_load. Tôi đã rất bối rối những gì đang xảy ra trong sản xuất env cho một ứng dụng mới. Và kể từ khi tôi bắt đầu học với Rails 5 tôi đã không đọc hướng dẫn di chuyển. Tôi đã gửi một vấn đề về tài liệu để hy vọng giải quyết vấn đề này: github.com/rails/rails/issues/27268 - akostadinov
thật ngạc nhiên, tôi có hai tệp trong lib dir, một tệp có thể dễ dàng có sẵn trong Thời gian chạy, nhưng một tệp khác phải được yêu cầu thủ công: D - illusionist
@Tobias Bạn đã kết thúc giải pháp nào? - geoboy
@geoboy Tôi mã nhóm (như Validators) trong các thư mục trực tiếp trong ứng dụng / thư mục vì mã có tự động được tải. - Tobias


Các câu trả lời:


Danh sách các thay đổi của tôi sau khi chuyển sang Rails 5:

  1. Địa điểm lib dir vào app bởi vì tất cả mã bên trong ứng dụng là tự động tải trong dev và háo hức được tải trong sản xuất và quan trọng nhất là tự động tải trong quá trình phát triển, do đó bạn không phải khởi động lại máy chủ mỗi khi bạn thực hiện thay đổi.
  2. Xóa bất kỳ require các câu lệnh trỏ đến các lớp của riêng bạn bên trong lib bởi vì tất cả chúng đều được tự động tải nếu tên tệp / dir của chúng là chính xác và nếu bạn rời khỏi require báo cáo nó có thể phá vỡ tự động tải. Thêm thông tin đây
  3. Bộ config.eager_load = true trong mọi môi trường để xem các vấn đề tải mã háo hức trong dev.
  4. Sử dụng Rails.application.eager_load! trước khi chơi với chủ đề để tránh lỗi "phụ thuộc vòng tròn".
  5. Nếu bạn có bất kỳ phần mở rộng ruby ​​/ rails nào thì hãy để mã đó bên trong cũ lib và tải chúng theo cách thủ công từ bộ khởi tạo. Điều này sẽ đảm bảo rằng các tiện ích được tải trước khi logic tiếp theo của bạn có thể phụ thuộc vào nó:

    # 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 }
    

105
2017-10-13 10:58



Vậy làm thế nào người ta sử dụng lib thư mục bây giờ? Ý tôi là di chuyển lib dir vào app dir có vẻ giống như một cách giải quyết. - Martin Svoboda
/app/lib/đặt một tập tin / lớp và nó không tự động tải. thử nghiệm trong đường ray 5.1, dự án mới - huan son
Cần lưu ý rằng bạn cần phải dừng mùa xuân. Tôi chuyển tất cả mọi thứ vào app / lib / và sau đó lãng phí một chút thời gian tự hỏi tại sao tôi vẫn không thể sử dụng các lớp học của tôi từ giao diện điều khiển. spring stop ftw :) - jacklin
Dòng sau sẽ đi đâu Rails.application.eager_load! - Steven Aguilar
@ Lev: Khi tôi làm điều đó, tôi thấy lỗi sau trong dev: NameError - uninitialized constant ApplicationController::JsonWebToken: Bạn có biết điều gì có thể xảy ra không? - geoboy


Tôi vừa mới sử dụng config.eager_load_paths thay vì config.autoload_paths như đề cập đến akostadinov trên github bình luận: https://github.com/rails/rails/issues/13142#issuecomment-275492070

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

Nó hoạt động trên môi trường phát triển và sản xuất.

Cảm ơn Johan để đề xuất thay thế #{Rails.root}/lib với Rails.root.join('lib')!


33
2017-07-08 11:32



Làm việc như một say mê. Tôi không thích cú pháp để thay đổi nó thành config.eager_load_paths << Rails.root.join('lib'). - Johan Wentholt


Tự động tải được tắt trong môi trường sản xuất vì an toàn luồng. Cảm ơn bạn @ Зелёный cho liên kết.

Tôi đã giải quyết vấn đề này bằng cách lưu trữ các tệp lib trong một lib thư mục trong của tôi app thư mục như được đề xuất Github. Mọi thư mục trong app thư mục được tải bởi Rails tự động.


24
2017-08-18 17:34



Nếu bạn không muốn đào sâu qua chuỗi thảo luận dài trên Github, bạn có thể tìm thấy giải thích chưng cất tại đây: collectiveidea.com/blog/archives/2016/07/22/… - Ernest
Tôi đã sử dụng config.eager_load_paths << "#{Rails.root}/lib", đó là IMO tốt hơn để làm theo đề nghị cấu trúc ứng dụng đường ray. - akostadinov
Đặt lib vào app/lib được khuyến cáo bởi thành viên đường ray github.com/rails/rails/issues/13142#issuecomment-275549669 - eXa
Điều này hoàn toàn hủy hoại mục đích của lib Là. Tôi sẽ chờ đợi cho bidlove hoặc DHH để kêu vang. Trong khi chờ đợi, tôi (cá nhân) khuyên bạn nên gắn bó với câu trả lời của @Lev Lukomsky. - Josh Brody
@JoshBrody Ý kiến ​​của tôi bây giờ là bạn không nên cần /lib thư mục nào cả. Bên thứ ba libs là hầu hết các đá quý thời gian và nếu không phải có một viên ngọc được tạo ra. Đối với các tệp khác, tôi tạo các thư mục cụ thể trong /app danh mục. Ví dụ validators. - Tobias


Phải có lý do khiến tính năng Tự động tải bị vô hiệu hóa trong quá trình sản xuất   mặc định.

Đây là một cuộc thảo luận dài về vấn đề này. https://github.com/rails/rails/issues/13142


17
2017-07-05 08:43





Điều này cho phép có tự động tải lib và cũng hoạt động trong môi trường sản xuất.

P.S. Tôi đã thay đổi câu trả lời của tôi, bây giờ nó thêm vào cả hai háo hức một đường dẫn autoload, bất kể môi trường, để cho phép làm việc trong môi trường tùy chỉnh quá (như sân khấu)

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

5
2018-01-29 13:50



Bạn có thể mở rộng về lý do tại sao điều này khắc phục được sự cố không? - Stuart.Sklinar
@ Stuart.Sklinar điều này cho phép có tự động tải lib, và hoạt động trong môi trường sản xuất quá. P.S. Tôi đã thay đổi câu trả lời của tôi, bây giờ nó thêm vào cả hai háo hức một đường dẫn autoload, bất kể môi trường, để cho phép làm việc trong môi trường tùy chỉnh quá (như sân khấu) - srghma
Bạn có thể mở rộng (Trong câu trả lời của bạn)? Mã chỉ có câu trả lời không thực sự giúp bất cứ ai hiểu tại sao nó nên được thực hiện "theo cách đó" - Tôi nên thêm tôi không phải là một dev Ruby, chỉ giúp làm sáng tỏ SO. Thêm một số bình luận vào "câu trả lời chỉ mã" sẽ cho nó một số ngữ cảnh thực tế. - Stuart.Sklinar
@ Stuart.Sklinar chắc chắn - srghma


Đối với bất cứ ai đấu tranh với điều này như tôi, nó không đủ để chỉ cần đặt một thư mục theo app/. Có, bạn sẽ nhận được tự động tải nhưng không cần thiết tải lại, yêu cầu phải tuân thủ các quy ước về không gian tên.

Đồng thời, sử dụng trình khởi tạo để tải cấp độ gốc cũ lib sẽ ngăn chặn tính năng tải lại trong quá trình phát triển.


2
2018-05-10 23:53





Trong một số ý nghĩa, đây là một cách tiếp cận thống nhất trong Rails 5 để tập trung cấu hình háo hức và tự động tải, đồng thời nó thêm đường dẫn tự động tải yêu cầu bất cứ khi nào mong muốn tải được cấu hình nếu không nó sẽ không thể hoạt động chính xác:

# 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
...

1
2018-05-29 16:29