Getting Started with Rails - walidacja komentarzy

Cześć wszystkim,

dopiero zacząłęm przygodę z Railsami i już mam problemy. Jak na razie jestem po “Rails for Zombies” i “Getting Started with Rails” z http://guides.rubyonrails.org.
Pytanie, pewnie banalne, dotyczy tego drugiego. Jeżeli tworzony post nie przechodzi walidacji, pojawia się taka fajna tabelka z listą błędów oraz zakreślone zostają elementy formularza, które te błędy spowodowały.
Chciałem zrobić coś podobnego dla komentarzy przy postach. W modelu dla komentarzy mam zdefiniowane walidacje i oczywiście komentarz się nie pojawia pod postem jeżeli ich nie spełnia.
Brakuje mi jednak tej notki, która pokaże, gdzie konkretnie w formularzu te błędy były.
Zupełnie nie wiem, z której strony się za to zabrać. Jak taka walidacja działa dla postów chyba rozumiem, bo tam akcja ‘create’ jeżeli nie udało się stworzyć posta, wykonuje ponownie render akcji ‘new’ i z niej mogę się dobrać do obiektu w zmiennej @post i sprawdzić, czy były błędy. Tutaj natomiast create robi redirect do akcji innego kontrolera. Myślałem, aby tą treść, dlaczego komentarz nie przeszedł walidacji wysyłać przy pomocy redirect_to @post, :notice => @comment.errors.full_messages.join(', ')
ale nie wiem, czy takie to powinno mieć zastosowanie. Argh, nie wiem, czy dobrze to wszystko wytłumaczyłem. Sorry za przydługiego posta pewnie z banalną sprawą. Oczywiście szukałem po forum, ale ciężko mi określić odpowiednie reguły wyszukiwania.

Poniżej akcja ‘create’ dla kontrolera komenatrzy i widok pokazujący post i formularz.

[code]class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.new(params[:comment])
@comment.save
redirect_to @post
end

end[/code]

[code]

<%= flash[:notice] %>

// wyswietlanie posta

Comments

// wyswietlanie komentarzy

// ten nieszczesny formularz

Add a comment:

<%= form_for([@post, @post.comments.build]) do |f| %>

<%= f.label :commenter %>
<%= f.text_field :commenter %>
<%= f.label :body %>
<%= f.text_area :body %>
<%= f.submit %>
<% end %>

<%= link_to ‘Edit’, edit_post_path(@post) %> |
<%= link_to ‘Back’, posts_path %>[/code]
btw. mógłby ktoś polecić co dalej? Ciągnąć te guides z rubyonrails.org, czy iść w innym kierunku? Ciężko mi to idzie.

Zrób analogicznie, czyli jeśli nie uda się stworzyć komentarza, to renderuj akcję ‘new’, a nie przekierowuj do innego kontrolera.

Problem w tym, że komentarze mają tylko akcję ‘create’ oraz ‘destroy’. Same komentarze wyświetlane są w widoku postów, i tam też tworzony jest formularz odwołujący się do Comments#create.
Myślałem, że można zrobić render do konkretnego posta, czyli zamiast “redirect_to @post” coś w stylu “render @post”. Nom, ale to nie bardzo chce działać.

Spróbuj z czymś takim:

<%= render :template => "posts/show" %>

Okej, jest zdecydowanie lepiej, tylko tego rendera umieściłem w kontrolerze. Teraz wygląda to tak:

[code]class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.new(params[:comment])

respond_to do |format|
  if @comment.save
    format.html { redirect_to @post, :notice => 'komentarz dodany' }
  else
    format.html { render "posts/show" }
  end
end

end
end[/code]
No i część widoku Posts#show coś w rodzaju:

[code]<% if defined? @comment and @comment.errors.any? %>


<%= pluralize(@comment.errors.count, “error”) %> prohibited this post from being saved:

  <ul>                                                                                                                                                            
  <% @comment.errors.full_messages.each do |msg| %>                                                                                                                    
    <li><%= msg %></li>                                                                                                                                                 
  <% end %>                                                                                                                                                              
  </ul>
</div>

<% end %>[/code]
I byłoby idealnie, gdyby nie to, że puste komentarze dalej przechodzą. Tzn. errory z walidacji się elegancko pokazują, ale wskakuje też na chwilę pusty komentarz z pustym ID. Piszę na chwilę, ponieważ po odświeżeniu stronki tego komentarza już nie ma. Czyżby samo “@comment.save” wrzucało do tabeli tymczasowo komentarz nawet jeżeli nie przechodzi walidacji modelu?
Uff, czy to jest naprawdę takie skomplikowane, czy może w życiu takie walidacjie formularza (przy nested resources i jednej akcji ‘show’) wykonuje się inaczej?

Pozdrawiam i dzięki za cierpliwość

Nic nie jest zapisywane w bazie, ale robiąc @post.comments.new(params[:comment]) masz doday ten komentarz do tablicy @post.comments. Możesz zrobić jeszcze raz załadować tą tablicę z bazy przez: @post.comments.reload
albo po prostu nie dodawać tam tego nowego komentarza robiąc po prostu:

@comment = Comment.new(params[:comment]) @comment.post_id = @post.id

Super, oba sposoby działają elegancko.
Dzięki jeszcze raz za cierpliwość.

Pozdrawiam