Rails 5: Załaduj pliki lib w środowisku produkcyjnym


132

Zaktualizowałem jedną z moich aplikacji z Rails 4.2.6 do Rails 5.0.0. Upgrade Przewodnik mówi, że funkcja Autoload jest teraz wyłączone w produkcji domyślnie.

Teraz zawsze pojawia się błąd na moim serwerze produkcyjnym, ponieważ ładuję wszystkie pliki lib z automatycznym ładowaniem w application.rbpliku.

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

Na razie mam ustawić config.enable_dependency_loadingaby trueale zastanawiam się, czy istnieje lepsze rozwiązanie tego. Musi istnieć powód, dla którego automatyczne ładowanie jest domyślnie wyłączone w środowisku produkcyjnym.


szalona rzecz, a dokumenty nadal mówią ci, żebyś wykonywał auto_load. Byłem bardzo zdezorientowany, co jest nie tak w środowisku produkcyjnym nowej aplikacji. Odkąd zacząłem uczyć się z Railsami 5, nie przeczytałem przewodnika po migracji. Mam nadzieję, że zgłosiłem
akostadinov

1
o dziwo, mam dwa pliki w libdir, jeden plik jest łatwo dostępny w Runtime, ale inny musi być wymagany ręcznie: D
iluzjonista

@Tobias Jakie rozwiązanie znalazłeś?
geoboy

@geoboy I kod grupy (jak Validators) w folderach bezpośrednio w katalogu aplikacji /, ponieważ kod jest ładowany automatycznie.
Tobias,

chodzi o właściwą ścieżkę pliku i definicji klasy Oto, co działa na mnie w Rails 5.2: ścieżka pliku: app/services/paylinx/paylinx_service.rbdefinicja klasy: module Paylinx class PaylinxService end end. Próbowałem tych autoload_pathsrzeczy. nie działa dla mnie.
NamNamNam

Odpowiedzi:


163

Moja lista zmian po przejściu na Rails 5:

  1. Umieść libdir w, appponieważ cały kod wewnątrz aplikacji jest automatycznie ładowany w wersji deweloperskiej i chętnie ładowany w wersji produkcyjnej, a co najważniejsze jest automatycznie ładowany podczas programowania, więc nie musisz ponownie uruchamiać serwera za każdym razem, gdy wprowadzasz zmiany.
  2. Usuń wszystkie requireinstrukcje wskazujące na twoje własne klasy wewnątrz, libponieważ i tak są one automatycznie ładowane, jeśli ich nazewnictwo plików / katalogów jest poprawne, a jeśli zostawisz requireinstrukcje, może to przerwać automatyczne ładowanie. Więcej informacji tutaj
  3. Ustaw config.eager_load = truewe wszystkich środowiskach, aby zobaczyć problemy z ładowaniem kodu w dev.
  4. Użyj Rails.application.eager_load!przed rozpoczęciem gry z wątkami, aby uniknąć błędów „zależności cyklicznych”.
  5. Jeśli masz jakieś rozszerzenia ruby ​​/ rails, zostaw ten kod w starym libkatalogu i załaduj je ręcznie z inicjatora. Zapewni to, że rozszerzenia zostaną załadowane przed dalszą logiką, która może na nim polegać:

    # 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
Jak więc libteraz używa się folderu? Chodzi mi o to, że przeniesienie libdir do appdir wydaje się być obejściem.
Martin Svoboda

3
/app/lib/umieścił plik / klasę i NIE ładuje się automatycznie. testowany na szynach 5.1, nowy projekt
Tim Kretschmer

31
Warto zauważyć, że musisz zatrzymać wiosnę. Przeniosłem wszystko do app / lib /, a potem zmarnowałem trochę czasu, zastanawiając się, dlaczego nadal nie mogę używać moich zajęć z konsoli. przystanek wiosenny ftw :)
jacklin

1
Gdzie poszłaby następująca liniaRails.application.eager_load!
Steven Aguilar

1
To może działać, ale nie jest to najlepsze rozwiązanie. Struktura folderów jest również semantyczna. Rzeczy w katalogu libmają inną postrzeganą bliskość do projektu niż rzeczy w appkatalogu. Kilka innych odpowiedzi jest lepszych niż ta.
CWitty

87

Po prostu użyłem config.eager_load_pathszamiast config.autoload_pathsjak wspomnieć akostadinov w komentarzu na github: https://github.com/rails/rails/issues/13142#issuecomment-275492070

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

Działa na środowisku deweloperskim i produkcyjnym.

Dzięki Johan dla propozycja zastąpienia #{Rails.root}/libz Rails.root.join('lib')!


3
Działa jak marzenie. Nie podobała mi się składnia, więc zmieniłem ją na config.eager_load_paths << Rails.root.join('lib').
3limin4t0r

2
Dla mnie to była najlepsza odpowiedź. Mój projekt rozpoczął się na Railsach 5.2 od zera, a folder / lib nadal był tworzony poza folderem / app. Nie widziałem dobrego powodu, aby go przenieść.
Samir Haddad

1
Tak, to działa! Wygląda na to, że deweloperzy Railsów naprawdę lubią powodować problemy z ładowaniem lib: D do następnego razu!
Damien Roche

1
To Rails 5.2 używa config.eager_load_paths += [Rails.root.join('lib')]zamiast tego, ponieważ config.eager_load_pathsjest zamrożoną tablicą
William Wong Garay

@WilliamWongGaray config.eager_load_paths jest tylko do odczytu, gdy próbujesz zmodyfikować go w inicjatorze. Po dodaniu ścieżek application.rbbędzie działać przy użyciu obu metod.
Michał Zalewski

32

Automatyczne ładowanie jest wyłączone w środowisku produkcyjnym ze względu na bezpieczeństwo wątków. Dziękuję @ Зелёный za link.

Rozwiązałem ten problem, przechowując pliki lib w libfolderze w moim appkatalogu, zgodnie z zaleceniami na Github . Każdy folder w appfolderze jest automatycznie ładowany przez Railsy.


6
Jeśli nie chcesz przekopywać się przez długi wątek dyskusyjny na Github, możesz znaleźć destylowane wyjaśnienie tutaj: collectidea.com/blog/archives/2016/07/22/…
Ernest

7
Użyłem config.eager_load_paths << "#{Rails.root}/lib", to lepsze IMO, aby podążać za zalecaną strukturą aplikacji rails.
akostadinov

2
Włączenie lib app/libjest zalecane przez członków rails github.com/rails/rails/issues/13142#issuecomment-275549669
eXa

4
To całkowicie rujnuje cel lib. Czekałbym, aż tuczna miłość lub DHH się włączy. W międzyczasie (osobiście) radziłbym trzymać się odpowiedzi @Lev Lukomsky.
Josh Brody,

@JoshBrody Moja opinia jest taka, że ​​w ogóle nie powinieneś potrzebować /libkatalogu. Biblioteki stron trzecich są w większości klejnotami, a jeśli nie, powinny zostać utworzone. Dla innych plików tworzę określone foldery w /appkatalogu. Na przykład validators.
Tobias


12

Pozwala to na automatyczne ładowanie lib i działa również w środowisku produkcyjnym.

PS Zmieniłem odpowiedź, teraz dodaje się do obu chętnych - automatyczne ładowanie ścieżek, niezależnie od środowiska, aby umożliwić pracę również w niestandardowych środowiskach (takich jak stage)

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

2
Czy mógłbyś wyjaśnić, dlaczego to rozwiązuje problem?
Stuart.Sklinar

@ Stuart.Sklinar pozwala to na automatyczne ładowanie biblioteki lib i działa również w środowisku produkcyjnym. PS Zmieniłem odpowiedź, teraz dodaje się do obu chętnych - automatyczne ładowanie ścieżek, niezależnie od środowiska, aby umożliwić pracę również w niestandardowych środowiskach (takich jak scena)
srghma

1
Czy mógłbyś rozwinąć (w swojej odpowiedzi)? Tylko kod odpowiedzi tak naprawdę nikomu nie pomagają zrozumieć, dlaczego powinno się to robić „w ten sposób” - powinienem dodać, że nie jestem programistą Ruby, tylko pomagam wyjaśnić SO. Dodanie komentarza do odpowiedzi „tylko kod” nadałoby jej rzeczywisty kontekst.
Stuart.Sklinar

1
@ Stuart.Sklinar sure
srghma

7

Po prostu zmień config.autoload_paths na config.eager_load_paths w pliku config / application.rb. Ponieważ w rails 5 automatyczne ładowanie jest domyślnie wyłączone dla środowiska produkcyjnego. Aby uzyskać więcej informacji, kliknij łącze .

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

Działa zarówno na potrzeby rozwoju środowiska, jak i produkcji.


5

W pewnym sensie tutaj jest ujednolicone podejście w Railsach 5 do scentralizowania konfiguracji przyspieszonego i automatycznego ładowania, jednocześnie dodaje wymaganą ścieżkę automatycznego ładowania, gdy zostanie skonfigurowane pożądane ładowanie, w przeciwnym razie nie będzie w stanie działać poprawnie:

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


0

Przeniesienie folderu lib do aplikacji pomogło rozwiązać problem, mój interfejs API na Twitterze nie działał w środowisku produkcyjnym. Miałem „niezainicjowaną stałą TwitterApi”, a moje API Twittera znajdowało się w folderze lib. Miałem config.autoload_paths += Dir["#{Rails.root}/app/lib"]plik application.rb, ale nie działał przed przeniesieniem folderu.

To załatwiło sprawę


-6

podsumowując odpowiedź Lwa: mv lib appwystarczyło, aby cały mój libkod był automatycznie ładowany / ponownie ładowany.

(szyny 6.0.0beta3, ale powinny działać dobrze również na szynach 5.x)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.