2013-02-28 20 views
6

Mam formularz umożliwiający użytkownikowi utworzenie pytania (w dodatku do modelu użytkownika, na stronie profilu znajduje się model zapytania z zagnieżdżonymi odpowiedziami). Przesyła on ze strony profilu użytkownika /views/users/show.html.erb do akcji create question_controller.rb. Jeśli to nie zostanie zatwierdzone, domyślnie dla Railsów jest renderowanie formularza (z nieprawidłowymi informacjami w formularzu do edycji przez użytkownika). Ponieważ jednak przesyłam formularz modelu pytania ze strony profilu użytkownika, wstępne wypełnienie nie następuje po nieudanej walidacji; użytkownik jest zmuszony ponownie wprowadzić wszystkie informacje w formularzu. Czy w tym kontekście istnieje sposób uzyskania formularza na stronie pokazu użytkowników w celu wypełnienia informacji wprowadzonych przed przesłaniem?Ponowne wypełnianie formularza po nieudanej walidacji

questions_controller

def create 
    @question = current_user.questions.build(params[:kestion]) 

    if @question.save 
     redirect_to current_user, :notice => "Successfully created question." 
    else 
     ###render :action => 'show' 
     redirect_to current_user 

    end 
    end 

Aktualizacja Zmieniłem końcówkę metody tworzenia zbyt

Redirect (: back), :notice => "something went wrong.try again" 

Ale nadal nie mogę dostać formularz do wypełnienia, a także komunikaty o błędach walidacji aren wyświetla się tylko informacja flash.

Aktualizacja Sposób pokaz kontrolera użytkowników tworzy nowe pytanie (wraz z obsługą)

def show 
     @user = User.find(params[:id]) 
     @question = Question.new 
     3.times {@question.answers.build} 

    end 

/views/users/show.html.erb

<%= form_for @question do |f| %> 
    <% if @question.errors.any? %> 
    <h2><%= pluralize(@question.errors.count, "error") %> prohibited this question 
    from being saved: </h2> 
    <ul> 
     <% @question.errors.full_messages.each do |msg| %> 
     <li> <%= msg %></li> 
    <% end %> 
    </ul> 
    <% end %> 
    <p> 
    <%= f.label :content, "Question"%> 
    <%= f.text_area :content, :class => 'span4', :rows => 1 %> 
    </p> 
    <p> 
    <%= f.label :link, "QuoraLink" %> 
    <%= f.text_field :link, :class => 'span4', :rows => 1 %> 
    </p> 
    <%= f.fields_for :answers do |builder| %> 
    <p> 
     <%= render 'answer_fields', :f => builder %> 
    </p> 
    <% end %> 
    <p><%= link_to_add_fields "Add Answer", f, :answers %></p> 
    <p><%= f.submit %></p> 
<% end %> 

się answer_fields Częściowo renderowane na pytania częściowe:

<p class="fields"> 
<%= f.label :content, "Answer..." %> 

    <%= f.text_field :content, :class => 'span3', :rows => 1%> 

    <%= f.label :correctanswer, "Correct" %> 
    <%= f.check_box :correctanswer, :class => 'span1' %> 

    <%= link_to_remove_fields "remove answer", f %>  
</p> 
+0

Jak wygląda metoda "pokaż" w swoim kontrolerze UsersController? To jest metoda, która wstępnie wypełnia formularz, jak rozumiem. Jak wygląda widok views/users/show.html. {Erb, haml}? Możesz przekazać tam parametry poprzez parametry ścieżki lub przez sesję [], ale prawdopodobnie będziesz potrzebował tam pewnych zmian. – moonfly

+0

@moonfly metoda show z kontrolera Użytkownicy "powinien" wstępnie wypełnij formularz (tj. To jest to, czego chcę), jeśli nie działa valiate, ale obecnie nie robi tego. Zaktualizowałem OP przy pomocy kodu, który zasugerowałeś. Czy możesz mi powiedzieć, w jaki sposób mogę zmienić powyższy kod, aby wstępnie wypełnić formularz, jeśli nie można go zweryfikować za pomocą żadnej z dwóch metod, do których się odnosisz? – Leahcim

Odpowiedz

1

Obecnie w widokach/Users/show.rb zrobić

@question = Question.new 

że tworzy pusty nowe pytanie. Następnie wypełniasz formularze tym pustym modelem. Co można zrobić zamiast tego jest:

if session[:question] 
    @question = @user.questions.new(session[:question]) 
    session[:question] = nil 
    @question.valid? # run validations to to populate the errors[] 
else 
    @question = Question.new 
end 

Teraz wszystko, co pozostało do zrobienia jest zapełnianie sesji [: Pytanie] w swoim questions_controller przed przekierowaniem do: controller => "użytkownicy",: action => "Show". Coś w rodzaju:

if @question.save 
    redirect_to current_user, :notice => "Successfully created question." 
else 
    session[:question] = params[:question] 
    redirect_to current_user 
end 

Może zajść potrzeba pracy nad serializacją/deserializacją dodatkowo do zapełniania/używania sesji [: pytanie]. Nie próbowałem kompilować, więc nie jestem pewien.

Wszystko to jest potrzebne, ponieważ po wykonaniu przekierowania do zakończenia przetwarzania żądania użytkownika przeglądarka użytkownika otrzymuje kod przekierowania z serwera i przechodzi do następnej strony, wysyłając nowe żądanie (które znajduje się na ścieżce, i ewentualnie kontroler/działanie, do którego przekierowałeś). Tak więc, jak tylko powrócisz z przetwarzania żądania, wszystkie twoje zmienne zostaną utracone. Do następnego wniosku zaczniesz od zera.

Podejście render :action => "show" (które było w oryginalnym rusztowaniu i które skomentowałeś) działało, ponieważ nie wróciłeś do użytkownika, ale po prostu renderowałeś szablon o określonej nazwie, używając zmiennych, które już posiadałeś (w tym @ pytanie, na które "save" zostało wywołane i nie powiodło się, a tym samym wewnętrzna walidacja została wywołana i wypełniła obiekt błędów).

Właściwie to przypomniało mi, że możesz chcieć zastosować inne podejście. Zamiast przekazywania parametrów przez sesję [] i przekierowania do UsersController, możesz wypełnić wszystkie wymagane zmienne i renderować widok z tego kontrolera. Jak poniżej:

if @question.save 
    redirect_to current_user, :notice => "Successfully created question." 
else 
    @user = current_user 
    render "users/show" 
end 
+0

Próbowałem drugiej sugestii renderowania "users/show", ale wpadłem na problem. Na górze /views/users/show.html.erb mam część nawigacyjną specyficzną dla zasobu użytkowników. Brakuje części nawigacyjnej podczas renderowania użytkowników/pokazywania na kontrolerze pytań. – Leahcim

+0

Rozwiązanie sesji jest obiecujące (tj. Mogę ponownie zaludnić pole pytania), ale zauważysz, że nie tylko tworzę nowe pytanie w akcji pokazowej, ale także trzy pola odpowiedzi: 3.times {@ question.answers.kompilacja} - w jaki sposób mogę je zapełnić informacjami o sesjach? – Leahcim

1

Po pierwsze, powód że użycie redirect_to zamiast render nie spowoduje ponownego wypełnienia formularza, oznacza to, że po wykonaniu redirect_to logika sterownika akcji jest wykonywana, natomiast użycie render zignoruje logikę sterownika.

Więc kiedy render :action => 'show' ("default" zachowanie), to czyni show.html.erb z @question zestaw jak ten:

@question = current_user.questions.build(params[:kestion]) 

Kiedy redirect_to current_user, to świadczy show.html.erb z @question ustawić za pomocą kodu w swoim działaniu show :

@question = Question.new 
3.times {@question.answers.build} 

Oto dlaczego otrzymujesz nowy (pusty) formularz, zamiast wstępnie wypełnionego.

Czy to naprawdę to ważne, że używasz redirect_to? Jeśli tak, musisz uzyskać metodę show, aby wykonać sprawdzanie poprawności. Na przykład, można przepisać metodę show do czegoś podobnego:

def show 
    @user = User.find(params[:id]) 
    if params.has_key?(:kestion) 
    @question = @user.questions.build(params[:kestion]) 
    else 
    @question = Question.new 
    3.times {@question.answers.build} 
    end 
end 

a następnie dokonać punkt formularz na tej stronie, z czymś takim:

<%= form_for(@question, url: users_path(@question.user) do |f| %> 
    ... 
<% end %> 

(w zależności od tego, jak Twoje trasy są skonfigurowane i nazwany).Oczywiście, w tym momencie wszystko staje się strasznie nie-REST, trochę bałaganu, a zdecydowanie nie sposób Railsowy robienia rzeczy. (Drugą, gorszą opcją byłoby przekierowanie z powrotem i przekazanie params za pomocą zapytania get). Moim zdaniem, tracisz dużo za niewielki zysk i nie jestem pewien, czy naprawdę bym to polecił.

+0

Zgadzam się z komentarzem "strasznie nie-RESTU". @Michael, jeśli dobrze rozumiem twoje intencje, wydaje się, że chcesz poprawić interfejs użytkownika i zezwolić na edytowanie pytań w formularzu użytkownika. Jeśli to zrobisz, prawdopodobnie ma sens wykonanie następnego logicznego kroku i zapisanie/zatwierdzenie pytań w metodzie aktualizacji UsersController # update. Upuść QuestionController i pozwól kontrolerowi użytkowników zająć się obydwoma modelami - użytkownikiem i pytaniem. – moonfly

Powiązane problemy