formularz dla zasobów zagnieżdżonych
Mam dwuczęściowe pytanie dotyczące form_for i zagnieżdżonych zasobów. Powiedzmy, że piszę silnik bloga i chcę odnieść komentarz do artykułu. Zdefiniowałem zagnieżdżony zasób w następujący sposób:
map.resources :articles do |articles|
articles.resources :comments
end
Formularz komentarza jest w programie.html.widok erb dla artykułów, pod samym artykułem, na przykład tak:
<%= render :partial => "articles/article" %>
<% form_for([ :article, @comment]) do |f| %>
<%= f.text_area :text %>
<%= submit_tag "Submit" %>
<% end %>
To daje błąd, " zwany id dla nil, który błędnie itp."I' ve also tried
<% form_for @article, @comment do |f| %>
Który renderuje poprawnie, ale odnosi się f. text_area do pola "tekst" artykułu zamiast komentarza i prezentuje html dla artykułu.atrybut tekstowy w tym obszarze tekstowym. Więc chyba też się mylę. Chcę formularza, którego 'submit' wywoła akcję create na CommentsController, z article_id w params, na przykład żądanie post do / articles / 1 / comments.
Druga część mojego pytania brzmi: jaki jest najlepszy sposób na stworzenie instancji komentarza na początek? Tworzę @komentarz w pokazuje działanie kontrolera ArticlesController, tak aby obiekt comment znajdował się w zasięgu helpera formula_for. Następnie w akcji create kontrolera CommentsController, tworzę nowy @ comment używając param przekazywanych z formula_for.
Dzięki!3 answers
Travis R ma rację. (Szkoda, że nie mogę ci pomóc. Sam to naprawiłem. Z tymi trasami:
resources :articles do
resources :comments
end
Dostajesz ścieżki typu:
/articles/42
/articles/42/comments/99
Przekierowanie do kontrolerów na
app/controllers/articles_controller.rb
app/controllers/comments_controller.rb
Tak jak jest napisane na http://guides.rubyonrails.org/routing.html#nested-resources , bez specjalnych przestrzeni nazw.
Ale częściowe i formy stają się trudne. Zwróć uwagę na nawiasy kwadratowe:
<%= form_for [@article, @comment] do |f| %>
Najważniejsze, jeśli chcesz URI, możesz potrzebować czegoś takiego jak to:
article_comment_path(@article, @comment)
Alternatywnie:
[@article, @comment]
Jak opisano w http://edgeguides.rubyonrails.org/routing.html#creating-paths-and-urls-from-objects
Na przykład wewnątrz zbioru częściowego z comment_item
dostarczonego do iteracji,
<%= link_to "delete", article_comment_path(@article, comment_item),
:method => :delete, :confirm => "Really?" %>
To, co mówi jamuraa, może działać w kontekście artykułu, ale nie działało dla mnie na różne inne sposoby.
Istnieje wiele dyskusji związanych z zagnieżdżonymi zasobami, np. http://weblog.jamisbuck.org/2007/2/5/nesting-resources
Co ciekawe, właśnie dowiedziałem się, że większość ludzi testy jednostkowe nie sprawdzają wszystkich ścieżek. Kiedy ludzie podążają za sugestią jamisbucka, kończą na dwóch sposobach dotarcia do zagnieżdżonych zasobów. Ich testy jednostkowe zazwyczaj dostają / wysyłają do najprostszych:
# POST /comments
post :create, :comment => {:article_id=>42, ...}
Aby przetestować trasę, którą mogą preferować, muszą zrobić to w ten sposób:]}
# POST /articles/42/comments
post :create, :article_id => 42, :comment => {...}
Nauczyłem się tego, ponieważ moje testy jednostkowe zaczęły awaria gdy przesiadłem się z tego:
resources :comments
resources :articles do
resources :comments
end
Do tego:
resources :comments, :only => [:destroy, :show, :edit, :update]
resources :articles do
resources :comments, :only => [:create, :index, :new]
end
Myślę, że jest ok mieć duplikaty tras, i przegapić kilka testów jednostkowych. (Dlaczego test? Ponieważ nawet jeśli użytkownik nigdy nie widzi duplikatów, formularze mogą się do nich odnosić, w sposób dorozumiany lub za pomocą nazwanych tras.) Jednak, aby zminimalizować zbędne powielanie, polecam to:
resources :comments
resources :articles do
resources :comments, :only => [:create, :index, :new]
end
Przepraszam za długą odpowiedź. Myślę, że niewielu ludzi zdaje sobie sprawę z subtelności.
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-05-06 15:21:36
Upewnij się, że oba obiekty zostały utworzone w kontrolerze: @post
i @comment
dla posta, np:
@post = Post.find params[:post_id]
@comment = Comment.new(:post=>@post)
Następnie w widoku:
<%= form_for([@post, @comment]) do |f| %>
Upewnij się, że jawnie zdefiniujesz tablicę w formula_for, a nie tylko rozdzielone przecinkami, jak powyżej.
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
2015-10-09 19:56:27
Nie musisz robić specjalnych rzeczy w formie. Wystarczy poprawnie zbudować komentarz w akcji show:
class ArticlesController < ActionController::Base
....
def show
@article = Article.find(params[:id])
@new_comment = @article.comments.build
end
....
end
A następnie zrób dla niego formularz w widoku artykułu:
<% form_for @new_comment do |f| %>
<%= f.text_area :text %>
<%= f.submit "Post Comment" %>
<% end %>
Domyślnie ten komentarz trafi do create
akcji CommentsController
, w którą prawdopodobnie będziesz chciał umieścić redirect :back
, aby przekierować cię z powrotem na stronę Article
.
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
2010-01-10 00:08:52