Rails-połączenie z, trasami i zagnieżdżonymi zasobami

Ponieważ moje zrozumienie zagnieżdżonych zasobów, na krawędziach szyn, nie powinno

link_to 'User posts', @user.posts

Wskaż

/users/:id/posts

?

Trasy.plik rb zawiera
map.resources :users, :has_many => :posts

Jeśli nie jest to zachowanie domyślne, czy można to osiągnąć robiąc coś innego?

Author: knoopx, 2009-10-10

4 answers

W tych samych liniach co Rishav:

link_to "User Posts", [@user, :posts]

Oto Wyjaśnienie z mojego bloga.

Naprawdę wcześnie na Railach, piszesz trasy w ten sposób:

redirect_to :controller => "posts", :action => "show", :id => @post.id

To, co zrobi, to posłuszne przekierowanie do show akcji wewnątrz PostsController i przejście wzdłuż id parametru z wartość whatever @post.id zwraca. Typowa odpowiedź 302.

Potem pojawił się Rails 1.2 i pozwolił ci używać pomocników routingu, takich jak to:

redirect_to post_path(@post)
I lud się ucieszył. To zrobiłoby dokładnie to samo. post_path tutaj zbudowalibyśmy trasę używając @post obiektu, który wyglądałby jak coś jak /posts/1, a następnie redirect_to odeśle odpowiedź 302 na tę trasę, a przeglądarka podąży za nią.

Potem późniejsze wersje (nie pamiętam która), zezwalały na składnię w ten sposób:

redirect_to @post
I ludzie radowali się po raz drugi.

Magia, ale nie naprawdę

Każda wystarczająco zaawansowana technologia jest nie do odróżnienia od magii.
Chociaż to wydaje się magiczne, to nie jest. To, co to robi, jest naprawdę bardzo, bardzo schludne. Metoda redirect_to, podobnie jak jej kuzyni link_to i form_for, używają wspólnej metody do budowania adresów URL, zwanej url_for. Metoda url_for zajmuje wiele różnych odmiany obiektów, takie jak ciągi znaków, skróty, a nawet instancje modeli, jak w powyższym przykładzie.

Co robi z te obiekty, więc, jest dość schludny. W przypadku wywołania redirect_to @post powyżej, sprawdza @post obiekt, widzi, że jest obiektem klasy Post (Zakładamy, tak czy inaczej) i sprawdza, czy obiekt ten został utrzymany w baza danych gdzieś przez wywołanie persisted? na nim.

Przez "persisted" mam na myśli, że obiekt Ruby ma gdzieś pasujący rekord w bazie danych. Metoda persisted? W Active Record jest zaimplementowana w następujący sposób:

def persisted?
  !(new_record? || destroyed?)
end

Jeśli obiekt nie został utworzony przez wywołanie takie jak Model.new wtedy nie będzie to nowy rekord, a jeśli nie było wywołanej metody destroy to nie będzie zniszczone. Jeśli oba te przypadki są prawdziwe, to oznacza to, że obiekt został najprawdopodobniej zapisany do bazy danych w formie rekordu.

Jeśli został utrzymany, to url_for wie, że obiekt ten można znaleźć gdzieś, i że miejsce, które można znaleźć jest najprawdopodobniej pod metodą o nazwie post_path. Więc nazywa tę metodę i przekazuje w wartość to_param tego obiektu, która zwykle jest id.

Krótko mówiąc, skutecznie to robi:

#{@post.class.downcase}_path(@post.to_param)

Co wychodzi na to:

post_path(1)

A gdy ta metoda zostanie wywołana, otrzymasz taki mały ciąg znaków:

"/posts/1"

Cudownie!

Nazywa się to routingiem polimorficznym. Możesz przekazać obiekt metodom takim jak redirect_to, link_to i form_for i będzie spróbuj ustalić poprawny adres URL tego, czego używać.

The forma formula_for

Teraz, kiedy kodujesz Rails, mogłeś użyć form_for w ten sposób bardzo dawno temu:

<% form_for @post, :url => { :controller => "posts", :action => "create" } do |f| %>
Oczywiście, z postępami w Rails można uprościć to do tego:]}
<% form_for @post, :url => posts_path do |f| %>

Ponieważ formularz domyślnie będzie miał metodę HTTP POST i dlatego żądanie do {[46] } trafi do create działanie PostsController, a nie działanie index, co miałoby wynik, gdyby było to żądanie GET.

But why stop tam? Dlaczego po prostu tego nie napiszesz?

<%= form_for @post do |f| %>
Osobiście nie widzę powodu, by tego nie robić... jeśli to coś tak prostego jak to. Metoda form_for używa url_for pod spodem, tak jak redirect_to aby ustalić, gdzie powinien pójść formularz. Wie, że obiekt @post należy do klasy Post (ponownie Zakładamy) i sprawdza, czy obiekt jest utrzymywany. Jeśli tak, to użyje post_path(@post). Jeśli nie, to posts_path.

Sama metoda form_for sprawdza, czy przekazany obiekt jest a jeśli tak, to domyślnie będzie to PUT HTTP metoda, inaczej a POST.

W ten sposób form_for Może być wystarczająco elastyczny, aby mieć identyczną składnię zarówno w widoku new, jak i {63]}. Staje się coraz bardziej i bardziej powszechne w dzisiejszych czasach, aby ludzie nawet umieścić swoje całe form_for tagi w jednym częściowym i włączyć go zarówno w new i edit stron.

Bardziej złożona forma

Więc form_for jest dość proste, gdy mijasz normalny obiekt, ale co się stanie, jeśli miniesz tablicę obiektów? W ten sposób, dla instancja:

<%= form_for [@post, @comment] do |f| %>

Cóż, zarówno url_for jak i form_for też się tym zająłeś.

Metoda url_for wykrywa, że jest to tablica i oddziela każdą część i sprawdza ją indywidualnie. Po pierwsze, co to jest Coś? W tym przypadku Załóżmy, że jest to Post instancja, która jest i ma id 1. Po drugie, co to jest @comment obiekt? Jest to instancja Comment, która nie została jeszcze / align = "left" /

Co url_for zrobi tutaj, to zbuduje metodę pomocniczą URL kawałek po kawałku, umieszczając każdą część w tablicy, łącząc ją w metodę routingu, a następnie wywołując tę metodę routingu z niezbędnymi argumentami.

Po pierwsze, wie, że obiekt @post należy do klasy Post i jest utrzymywany, dlatego helper URL rozpocznie się od post. Po drugie wie, że obiekt @comment należy do klasy Comment i jest Nie i dlatego comments będzie podążać post w kompilacji pomocniczej adresu URL. Części, które url_for teraz wie o [:post, :comments].

Metoda

Metoda url_for łączy te poszczególne części z podkreśleniem, tak że staje się post_comments, a następnie dodaje _path do końca, co daje post_comments_path. Następnie przechodzi tylko w obiektach do wywołania tej metody, co skutkuje wywołaniem takim jak: {116]}

post_comments_path(@post)

Wywołanie tej metody skutkuje następująco:

"/posts/1/comments"

Najlepsza część? form_for will nadal wiem, aby używać POST, jeśli @comment obiekt nie jest trwałym obiektem, i PUT, jeśli jest. Dobry należy pamiętać, że form_forjest zawsze dla ostatniego obiektu określonego w tablicy. Obiekty przed nim są tylko jego gniazdowanie, nic więcej.

Im więcej obiektów zostanie dodanych, tym więcej razy url_for zrobi twarde podwórka i zbuduje ścieżkę... chociaż polecam trzymaj to tylko w dwóch częściach.

Forma symboliczna

Teraz, że omówiliśmy użycie tablicy zawierającej obiekty dla form_for, przyjrzyjmy się innemu powszechnemu użyciu. Tablica zawierająca co najmniej jeden obiekt symbolu, taki jak ten:

<%= form_for [:admin, @post, @comment] do |f| %>

To, co robi tutaj metoda url_for jest bardzo proste. Widzi, że istnieje Symbol i przyjmuje to tak, jak jest. Pierwsza część url będzie po prostu tym samym symbolem: admin. Adres URL, który url_for zna w tym momencie, to po prostu [:admin].

Następnie url_for przechodzi przez pozostałe części tablicy. W w tym przypadku, Załóżmy, że zarówno @post, jak i @comment są utrzymane i że mają ID odpowiednio 1 i 2. Te same zajęcia co wcześniej. url_for następnie dodaje post do adresu URL, który buduje, i comment również, w wyniku [:admin, :post, :comment].

Następnie następuje połączenie, w wyniku czego powstaje metoda admin_post_comment_path, a ponieważ zarówno @post, jak i @comment są tutaj, są one przekazywane w wyniku wywołania tej metody:

admin_post_comment_path(@post, @comment)

Który (zazwyczaj) zamienia się w to ścieżka:

/admin/posts/1/comments/2

Możesz użyć tablicy w postaci trasowania polimorficznego z redirect_to, link_to i form_for metody. Jest chyba inny metody, których teraz nie pamiętam, też mogą to zrobić... ogólnie rzecz biorąc, to wszystko w Rails, które normalnie przyjmowałoby adres URL.

Nie ma potrzeby budowania adresów URL w dowolnej wersji Rails większej niż 2 używając hashów; to dość stara szkoła.

Zamiast tego, eksperymentuj z nową wiedzą o routingu polimorficznym i wykorzystaj to jak najlepiej.

 53
Author: Ryan Bigg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-09 04:25:50

To powinno zadziałać:

 
 link_to "User Posts", user_posts_path(@user)

Więcej szczegółów na stronie:

Http://guides.rubyonrails.org/routing.html

 15
Author: Rishav Rastogi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-10 14:06:37

link_to zastosowania url_for które wykorzystuje polymorphic_url.

polymorphic_url:

Dlatego, jak mówili inni, powinieneś użyć:

link_to 'User Posts', [@user, :posts]

Dla którego ścieżka jest:

user_posts_path(@user)
^^^^ ^^^^^      ^^^^^
1    2          3
  1. Klasa @user ponieważ jest rekordem aktywnym
  2. Konwertuj Na string ponieważ symbol
  3. Dodaj jako argument wywołania, ponieważ active record

To buduje dobrą metodę pomocniczą.

 2
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-09 11:53:07

Oto jak połączyć się z zagnieżdżonym zasobem w najnowszych Rails:

Link_to 'Destroy Comment', post_comment_path (comment.post, komentarz)

Uwaga: Jest to częściowe, więc nie ma @.

 1
Author: Chloe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-09 17:11:48