Rails 4: organizować modele szyn w ścieżce podrzędnej bez modeli przestrzeni nazw?

80

Czy można mieć coś takiego?

app/models/
app/models/users/user.rb
app/models/users/education.rb

Celem jest lepsze uporządkowanie folderu / app / models , ale bez konieczności określania przestrzeni nazw modeli.

Pytanie bez odpowiedzi dla Rails 3 jest tutaj: Railsy 3.2.9 i modele w podfolderach .

Wydaje się , że określenie table_name z przestrzeniami nazw działa (zobacz podfolder modelu Rails 4 ), ale chcę to zrobić bez przestrzeni nazw .

Rubytastic
źródło
Zrozumiałem, że nie potrzebujesz przestrzeni nazw, ale myślę, że najlepszym sposobem na to jest użycie ActiveSupport Concerns.
Nando Sousa
2
@NandoSousa. Nie. ActiveSupport Obawy dotyczą zachowania współdzielonego. Sposób korzystania z modeli.
berkes

Odpowiedzi:

116

Domyślnie Railsy nie dodają podfolderów katalogu models do ścieżki automatycznego ładowania. Dlatego może znaleźć tylko modele z przestrzeniami nazw - przestrzeń nazw oświetla podkatalog, w którym ma zajrzeć.

Aby dodać wszystkie podfoldery aplikacji / modeli do ścieżki automatycznego ładowania, dodaj następujące elementy do pliku config / application.rb :

config.autoload_paths += Dir[Rails.root.join("app", "models", "{*/}")]

Lub, jeśli masz bardziej złożony katalog app / models , powyższa metoda globalnego łączenia wszystkich podfolderów app / models może nie działać poprawnie. W takim przypadku możesz to obejść, będąc nieco bardziej precyzyjnym i dodając tylko określone podfoldery:

config.autoload_paths += Rails.root.join("app", "models", "<my_subfolder_name1>")
config.autoload_paths += Rails.root.join("app", "models", "<my_subfolder_name2>")

UPDATE dla Rails 4.1+

Od wersji Rails 4.1 generator aplikacji nie zawiera config.autoload_pathsdomyślnie. Zwróć więc uwagę, że powyższe naprawdę należy do config / application.rb .

AKTUALIZACJA

Naprawiono przykłady ścieżek automatycznego ładowania w powyższym kodzie do użycia {*/}zamiast {**}. Koniecznie przeczytaj komentarz muichkine, aby uzyskać szczegółowe informacje.

pdobb
źródło
6
Próbowałem, ale kończy się niepowodzeniem ze stałą Unable to autoload User :: Credits, oczekiwano /srv/books/app/models/user/credits.rb, aby ją zdefiniować. Więc nadal nie można nazwać plików z odstępami. Umieściłem je nad wpisem lib zgodnie z sugestią.
Rubytastic
1
Ten błąd to właściwie dobra wiadomość. To znaczy, że znalazł plik. Ale używasz tutaj dziwnej liczby mnogiej. Jeśli nazwa pliku jest app/models/user/credits.rbnastępnie upewnij się, że nazwa klasy w pliku jest również liczba mnoga: class Credits. Ale radziłbym użyć standardu Rails i zrobić to class Crediti nazwę pliku app/models/user/credit.rb(modele powinny być pojedyncze). Tak czy inaczej, to powinien być problem. Daj mi znać!
pdobb
1
W konfiguracji Rails 4.1 używamconfig.autoload_paths += %W( #{Rails.root}/app/models/namespace #{Rails.root}/app/models/other_namespace )
Epigene
14
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]działa, ale spowalnia aplikację, szczególnie w trybie programistycznym, w którym aplikacja jest często ponownie ładowana. Powodem jest to, że nie wolno dodawać wszystkich plików do autoload_paths, ale tylko foldery główne, z których można wywnioskować nazwy plików i moduły. W prostych terminach, jeśli masz tylko jeden poziom podfolderów w modelach i nie masz modeli przestrzeni nazw, powinieneś zrobić tylko to, config.autoload_paths += Dir[Rails.root.join('app', 'models', '*/')]co dodaje tylko pierwszy poziom podkatalogów. To samo dla liblub innych ścieżek.
muichkine
3
@pdobb to doświadczenie :) Jeśli spojrzysz na to, jak działa automatyczne ładowanie, zobaczysz, że w ogóle auto_loading_pathssię zapętla, do którego dodaje wnioskowanie dla modelu. Na przykład, jeśli masz NameSpace::Model, spróbuje znaleźć we wszystkich autoloading_paths a path/namespace/model. Może to oczywiście pasować tylko wtedy, gdy pathjest katalogiem. Z reguły w celu autoload_pathsuzyskania maksymalnej wydajności należy mieć tylko katalogi w katalogu . Mam nadzieję, że to pomoże.
muichkine