Powiedz, że mam model szyny o nazwie Thing. Rzecz ma atrybut url, który można opcjonalnie ustawić na adres URL gdzieś w Internecie. W widoku kodu potrzebuję logiki, która wykonuje następujące czynności:
<% if thing.url.blank? %>
<%= link_to('Text', thing_path(thing)) %>
<% else %>
<%= link_to('Text', thing.url) %>
<% end %>
Ta logika warunkowa w widoku jest brzydka. Oczywiście mógłbym zbudować funkcję pomocnika, która zmieniłaby widok na to:
<%= thing_link('Text', thing) %>
To rozwiązuje problem z gadatliwością, ale naprawdę wolałbym mieć funkcjonalność w samym modelu. W takim przypadku kod widoku to:
<%= link_to('Text', thing.link) %>
To oczywiście wymagałoby metody link w modelu. Oto, co powinien zawierać:
def link
(self.url.blank?) ? thing_path(self) : self.url
end
Do rzeczy pytania rzecz_path () jest niezdefiniowaną metodą w kodzie modelu. Zakładam, że możliwe jest „wciągnięcie” niektórych metod pomocniczych do modelu, ale jak? Czy istnieje prawdziwy powód, dla którego routing działa tylko na kontrolerze i wyświetla warstwy aplikacji? Mogę wymyślić wiele przypadków, w których kod modelu może wymagać obsługi adresów URL (integracja z systemami zewnętrznymi itp.).
źródło
Odpowiedzi:
W Railsach 3, 4 i 5 możesz użyć:
na przykład
źródło
:host
opcji wszędzie i ustaw ją raz w plikach konfiguracyjnych swojego środowiska:Rails.application.routes.default_url_options[:host] = 'localhost:3000'
include Rails.application.routes.url_helpers
działa na mnie w Rails 4.1Znalazłem odpowiedź dotyczącą tego, jak to zrobić samodzielnie. W kodzie modelu po prostu wstaw:
Dla szyn <= 2:
W przypadku szyn 3:
To w magiczny sposób
thing_path(self)
zwraca adres URL bieżącej rzeczy lubother_model_path(self.association_to_other_model)
inny adres URL.źródło
include Rails.application.routes.url_helpers
Może się również okazać, że następujące podejście jest czystsze niż w przypadku każdej metody:
źródło
undefined local variable or method 'url_helpers' for Event:Class
błąd ... :(undefined method url_helpers
. Co ja zrobięclass
, jak pokazano w odpowiedzi. Jeśli Twoja klasa Modelu już się rozszerza,< ApplicationRecord
to nie zadziała?Każda logika związana z tym, co jest wyświetlane w widoku, powinna zostać przekazana do metody pomocniczej, ponieważ metody w modelu służą wyłącznie do obsługi danych.
Oto, co możesz zrobić:
źródło
Naprawdę lubię stosować czyste rozwiązanie.
Pochodzi z http://hawkins.io/2012/03/generating_urls_whenever_and_wherever_you_want/
źródło
Chociaż może istnieć sposób, aby nie dopuścić do tego rodzaju logiki poza modelem. Zgadzam się, że nie powinieneś umieszczać tego w widoku ( utrzymuj go chudego ), ale chyba że model zwraca adres URL jako kawałek danych do kontrolera, rzeczy związane z routingiem powinny znajdować się w kontrolerze.
źródło
(Edycja: Zapomnij o mojej poprzedniej paplaninie ...)
Ok, mogą zdarzyć się sytuacje, w których możesz pójść albo do modelu, albo do innego adresu URL ... Ale tak naprawdę nie sądzę, że to należy do modelu, widok (a może model) brzmi bardziej odpowiedni.
O trasach, o ile wiem, trasy służą do akcji w kontrolerach (które zwykle „magicznie” używają widoku), a nie bezpośrednio do widoków. Administrator powinien obsługiwać wszystkie żądania, widok powinien prezentować wyniki, a model powinien obsługiwać dane i podawać je do widoku lub kontrolera. Słyszałem tutaj wiele osób mówiących o trasach do modeli (do tego stopnia, że prawie to uwielbiam), ale jak rozumiem: trasy idą do kontrolerów. Oczywiście wiele kontrolerów jest kontrolerami dla jednego modelu i jest często nazywane
<modelname>sController
(np. „UsersController” jest kontrolerem modelu „User”).Jeśli zauważysz, że piszesz nieprzyjemne ilości logiki w widoku, spróbuj przenieść logikę w bardziej odpowiednie miejsce; logika żądania i komunikacji wewnętrznej prawdopodobnie należy do kontrolera, logika związana z danymi może być umieszczona w modelu (ale nie logika wyświetlania, która zawiera tagi łącza itp.), a logika, która jest czysto związana z wyświetlaniem, zostanie umieszczona w pomocniku.
źródło