Pytanie Railsy 5: Wczytaj pliki lib do produkcji


Uaktualniłem jedną z moich aplikacji z Rails 4.2.6 do Rails 5.0.0. The Przewodnik aktualizacji mówi, że funkcja automatycznego ładowania jest domyślnie wyłączona w produkcji.

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

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

Na razie ustawiłem config.enable_dependency_loading do true ale zastanawiam się, czy istnieje lepsze rozwiązanie tego problemu. Musi być jakiś powód, dla którego automatyczne ładowanie jest domyślnie wyłączone w produkcji.


76
2017-07-05 08:30


pochodzenie


Czy kiedykolwiek to rozgryzłeś? - dkam
szalone rzeczy, a dokumenty nadal mówią, aby zrobić auto_load. Byłem bardzo zdezorientowany, co dzieje się źle w środowisku produkcyjnym dla nowej aplikacji. A ponieważ zacząłem uczyć się z Rails 5, nie czytałem podręcznika migracji. Złożyłem dokument, aby uzyskać rozwiązanie problemu: github.com/rails/rails/issues/27268 - akostadinov
zadziwiająco, mam dwa pliki w lib dir, jeden plik jest łatwo dostępny w środowisku wykonawczym, ale inny musi być wymagany ręcznie: D - illusionist
@Tobias Z jakiego rozwiązania skorzystałeś? - geoboy
@geoboy I kod grupowy (np Validators) w folderach bezpośrednio w katalogu app /, ponieważ kod jest ładowany automatycznie. - Tobias


Odpowiedzi:


Moja lista zmian po przejściu do Rails 5:

  1. Miejsce lib w reżyserii app ponieważ cały kod w aplikacji jest autoloaded w dev i chętny załadowany w prod i co najważniejsze jest autoreloaded w fazie rozwoju, więc nie musisz restartować serwera za każdym razem, gdy wprowadzasz zmiany.
  2. Usuń wszystkie require wyciągi wskazujące na twoje własne klasy w środku lib ponieważ i tak wszystkie są ładowane automatycznie, jeśli ich nazwy plików / nazw są poprawne, a jeśli odejdziesz require stwierdzenia, że ​​może przerwać autoreloadowanie. Więcej informacji tutaj
  3. Zestaw config.eager_load = true we wszystkich środowiskach, aby zobaczyć problemy z ładowaniem kodu w dev.
  4. Posługiwać się Rails.application.eager_load! przed odtwarzaniem z wątkami, aby uniknąć błędów związanych z cykliczną zależnością.
  5. Jeśli masz jakieś rozszerzenia ruby ​​/ rails, zostaw ten kod w starym lib i załaduj je ręcznie z inicjalizatora. Zapewni to ładowanie rozszerzeń 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 }
    

105
2017-10-13 10:58



Więc w jaki sposób się używa lib folder teraz? Mam na myśli przeprowadzkę lib w reżyserii app dir wydaje się trochę jak obejście. - Martin Svoboda
/app/lib/umieścił plik / klasę i NIE jest automatycznie ładowany. testowane w szynach 5.1, nowy projekt - huan son
Warto zauważyć, że musisz zatrzymać wiosnę. Przeniosłem wszystko do aplikacji / lib /, a następnie zmarnowałem trochę czasu zastanawiając się, dlaczego nadal nie mogę używać moich klas z konsoli. wiosenny przystanek ftw :) - jacklin
Gdzie pójdzie następująca linia Rails.application.eager_load! - Steven Aguilar
@Lev: Kiedy to zrobię, widzę następujący błąd w dev: NameError - uninitialized constant ApplicationController::JsonWebToken: Czy wiesz, co może się dziać? - geoboy


Właśnie użyłem config.eager_load_paths zamiast config.autoload_paths jak wspomnieć o akostadinovie na komentarzu 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 programistycznym i produkcyjnym.

Dzięki Johan dla sugestii do zamiany #{Rails.root}/lib z Rails.root.join('lib')!


33
2017-07-08 11:32



Działa jak marzenie. Nie podobała mi się składnia, więc zmienili ją config.eager_load_paths << Rails.root.join('lib'). - Johan Wentholt


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 lib folder w moim app katalog zgodnie z zaleceniami Github. Każdy folder w app folder zostanie załadowany automatycznie przez Rails.


24
2017-08-18 17:34



Jeśli nie chcesz przeglądać długiego wątku dyskusji na Githubie, tutaj znajdziesz wytłumaczone wyjaśnienie: collectiveidea.com/blog/archives/2016/07/22/... - Ernest
użyłem config.eager_load_paths << "#{Rails.root}/lib", to lepiej IMO przestrzegać zalecanej struktury aplikacji szyn. - akostadinov
Wprowadzanie lib app/lib jest zalecane przez członków rails github.com/rails/rails/issues/13142#issuecomment-275549669 - eXa
To całkowicie niszczy cel lib jest. Zaczekałbym na zaproszenie do przetargu lub DHH. W międzyczasie (osobiście) polecam trzymać się odpowiedzi @Lev Lukomsky'ego. - Josh Brody
@JoshBrody Moja opinia jest taka, że ​​nie powinieneś tego potrzebować /lib w ogóle katalog. Biblioteki innych firm są najczęściej klejnotami czasu, a jeśli nie, to powinien powstać klejnot. W przypadku innych plików tworzę określone foldery w /app informator. Na przykład validators. - Tobias


Musi istnieć powód, dla którego automatyczne ładowanie jest wyłączone w produkcji według   domyślna.

Oto długa dyskusja na ten temat. https://github.com/rails/rails/issues/13142


17
2017-07-05 08:43





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

P.S. Zmieniłem swoją odpowiedź, teraz dodaje ona zarówno chętnych - ścieżek automatycznych, niezależnie od środowiska, aby umożliwić pracę w niestandardowych środowiskach (takich jak etap)

# 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



Czy możesz wyjaśnić, dlaczego to rozwiązuje problem? - Stuart.Sklinar
@ Stuart.Sklinar pozwala na automatyczne ładowanie biblioteki i działa również w środowisku produkcyjnym. P.S. Zmieniłem swoją odpowiedź, teraz dodaje ona zarówno chętnych - ścieżek automatycznych, niezależnie od środowiska, aby umożliwić pracę w niestandardowych środowiskach (takich jak etap) - srghma
Czy możesz rozwinąć (w twojej odpowiedzi)? Tylko odpowiedź na kod nie pomaga nikomu zrozumieć, dlaczego należy to zrobić "w ten sposób" - powinienem dodać, że nie jestem deweloperem Ruby, tylko pomagam wyjaśnić SO. Dodanie komentarza do "odpowiedzi tylko kodu" dałoby mu pewien aktualny kontekst. - Stuart.Sklinar
@ Stuart.Sklinar pewnie - srghma


Dla każdego, kto boryka się z tym jak ja, nie wystarczy po prostu umieścić w nim katalog app/. Tak, dostaniesz automatyczne ładowanie, ale nie będzie to konieczne ponowne ładowanie, które wymaga spełnienia konwencji nazw.

Ponadto za pomocą inicjalizatora do ładowania starego poziomu root lib zapobiegnie przeładowaniu podczas programowania.


2
2018-05-10 23:53





W pewnym sensie, tutaj jest ujednolicone podejście w Rails 5, aby scentralizować chętną i autoloadową konfigurację, w tym samym czasie dodaje wymaganą ścieżkę automatycznego ładowania zawsze, gdy konfigurowane jest obciążenie obciążone, 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
...

1
2018-05-29 16:29





Przeniesienie folderu lib do aplikacji pomogło rozwiązać problem, moje api API na Twitterze nie działałyby w produkcji. Miałem "niezainicjowaną stałą TwitterApi", a mój Twitter API znajdował się w moim folderze lib. miałem config.autoload_paths += Dir["#{Rails.root}/app/lib"] w moim application.rb, ale nie działało przed przeniesieniem folderu.

To załatwiło sprawę


0
2017-11-15 23:54