2011-01-17 11 views

Odpowiedz

74

Istnieje kilka powodów, dla których możesz potrzebować łącza w modelu. Tak, @andy, to naruszenie MVC, ale to nie znaczy, że powinieneś zdobyć punkty za brak odpowiedzi na pytanie.

@schwabsauce, to łatwiejsze. Pierwsza linia nie jest nawet absolutnie konieczna, jeśli robisz to w inicjatorze lub czymś podobnym. To samo działa dla .sanitize i .raw i całego ładunku innych niesamowitych funkcji.

ActionView::Base.send(:include, Rails.application.routes.url_helpers) 
ActionController::Base.helpers.link_to(whatever) 

Jeśli chcesz użyć autopaths może trzeba to zrobić wewnątrz link_to:

Rails.application.routes.url_helpers.page_path(@page) 
+0

To pytanie zostało zadane przed chwilą iw tej chwili rady @ andy pomogły mi rozwiązać ten problem. Masz jednak rację, nie odpowiadając na faktyczne pytanie. – Krule

-6

Nie bez hackery.

Jeśli uważasz, że potrzebujesz modelu link_to, najprawdopodobniej naruszysz zasadę Model-View-Controller architecture.

Model powinien być miejscem dla danych i logiki biznesowej, ale generowanie linków prawie na pewno jest zadaniem kontrolera lub widoku (lub, w szczególności Railsów, w klasie pomocnika).

+1

Dziękuję. Przeniesiono rzeczy, aby wyświetlić pomocnika. Wszystko pasuje teraz. – Krule

+18

Istnieją dobre powody, aby używać pomocników w modelach. Ale bardziej do rzeczy, jeśli masz zamiar zaoferować opinię, przynajmniej zaoferuj rozwiązanie na wypadek, gdyby się zastanowili. Możliwe, że ktoś z 2k rep ma głowę na prostej. –

5

Dostałem to do pracy z następującymi inkluzji:

include ActionView::Helpers::UrlHelper 
include ActionController::UrlFor 
include Rails.application.routes.url_helpers 

cattr_accessor :controller 
def controller; self.class.controller; end 
def request; controller.request; end 

Wtedy w moim kontrolera I zaludnionych atrybut (tworzenie kontrolera od podstaw wymaga znacznych ilości danych w argumentach hash).

Lead.controller = self 
+1

fwiw, Dokumentacja Rails prowadzi do tego rozwiązania. Dokumenty ActionDispatch :: Routing :: UrlFor wskazują, że "Wskazówka: jeśli potrzebujesz generować adresy URL ze swoich modeli lub w innym miejscu, to ActionController :: UrlFor jest tym, czego szukasz." Następnie, gdy podasz ten plik, wyświetli się komunikat o błędzie: raise "Aby użyć #url_for, musisz wyraźnie włączyć obsługę routingu." "Na przykład" include Rails.application.routes.url_helpers " Myślę, że to jest dopuszczalne przez konwencje Railsowe - czasami jest to najlepszy sposób/najlepsze miejsce do wygenerowania linku :) – schwabsauce

+0

Tak, na przykład, jeśli twój model obsługuje autoryzację płatności dla strony trzeciej, bramy zewnętrznej i musi generować adresy URL zwracanych/anulowanych wróć do aplikacji. – hoffmanc

30

Bądź bardzo ostrożny po poradę przedstawionym na stanowisku Chucka jeśli robisz to w Rails 3.2. 1. Wydaje się, że takie podejście nie jest bezpiecznym sposobem obejścia problemu, włączając pomocnika link_to w klasach bez widoku w Railsach 3.2.1. Istnieje bezpieczniejsza metoda (która działa dla nas w każdym przypadku) opisana poniżej.

Kiedy użyliśmy podejścia na stanowisku Chucka w jednej z naszych lekcji, okazało się, że bardzo kłopotliwe i trudne do usunięcia są konsekwencje. W efekcie pojawiły się efekty uboczne/błędy, które pojawiały się tylko w bardzo specyficznych (i rzadkich) okolicznościach.

Problem, o ile możemy powiedzieć, że jest to linia:

ActionView::Base.send(:include, Rails.application.routes.url_helpers) 

mówi ActionView::Base włączenie Rails.application.routes.url_helpers, który ActionView::Base widocznie już robi na własną rękę. Posiadanie go po raz drugi, wydaje się powodować ponowną inicjalizację stanu tras (@_routes w klasach, które zawierały moduł ActionDispatch :: Routing :: UrlFor).

Prowadzi to do pozornie przypadkowe i niewyjaśnione „niezdefiniowana metoda«url_for»do zera: NilClass” wyjątków w widokach, które starają się połączyć, bezpośrednio lub pośrednio, metoda url_for poActionView::Base włączyło url_helpers po raz drugi.

Rozwiązaniem, które działało dla nas, było zamiast powiedzieć ActionView::Base, aby ponownie dodać url_helpers, wystarczy sam moduł UrlHelper, gdziekolwiek go potrzebujesz.

Wtedy, gdy trzeba użyć link_to i mieć dostęp do ścieżki można po prostu zrobić to (zakładając login_path jest ważna dla aplikacji):

include ActionView::Helpers::UrlHelper 
... 
link = link_to('here', Rails.application.routes.url_helpers.login_path) 

Zajęło nam to bardzo dużo czasu i sporo drapania głowy w celu wyśledzenia błędów spowodowanych przez podwójne włączenie i po prostu chciałem ostrzec innych, aby zachowali ostrożność podczas modyfikowania zachowania klas bazowych Rails.

+0

Dziękujemy za udostępnienie! Cieszę się, że znalazłeś lepszy sposób! –

+1

Jedna linijka: 'include ActionView :: Helpers :: UrlHelper' – karlingen

+0

@karlingen - pomijanie odniesienia do' Rails.application.routes ... 'może prowadzić do wiadomości" argumenty przekazane do url_for nie mogą być obsługiwane. wymagają tras lub zapewniają własną implementację " – Del

2

link_to pomocnika, MVC naruszenie

Co powiedział Andy,

jeśli jesteś generowania kodu HTML w modelu prawdopodobnie trzeba zrobić duży długie spojrzenie na to, co robisz i dlaczego.

URL pomocnicy

URL z drugiej strony często się przydać zewnątrz kodu widok-kontroler, we wszystkich rodzajach usług/form/api/... Klasy Na przykład, nawet jeśli was w modelach musieć.

Tak, Rails.application.routes.url_helpers to moduł, ale to nie znaczy, należy po prostu umieścić go gdziekolwiek lub śmieszne rzeczy rozpocznie się dzieje, jak Gary umieścić go:

https://www.destroyallsoftware.com/blog/2011/one-base-class-to-rule-them-all

Co można zrobić to:

delegate :url_helpers, :to => 'Rails.application.routes' 

a następnie użyć, na przykład

url_helpers.home_url 
Powiązane problemy