Repopulating a form when validation fails

I have a form so that the user can ask a question (in addition to the user model, there is a question model on the profile page with nested answers). It sends the create_controller.rb action to the user profile page /views/users/show.html.erb. If this is not confirmed, I think that by default for Rails it is necessary to display the form (with incorrect information in the form for user editing). However, since I submit the form for the question model on the user profile page, preliminary preparation does not occur if the validation fails; the user is forced to enter all the information in the form again. Is there a way in this context to get a form on the user display page to fill in the information that was entered before submitting?

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 

Update I also changed the end of the creation method

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

But I still can’t get the form to fill out, and verification error messages are not displayed, only a flash notification.

Update The show method of the user controller creates a new question (with the user)

  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 %> 

parts of answers partially displayed from questions, partial

 <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> 
+6
source share
2 answers

Currently in views / users / show.rb you are doing

 @question = Question.new 

which creates an empty new question. Then you fill out the forms with this empty model. Instead, you can:

 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 

Now all you have to do is fill out the [: question] session in your controller_ question before redirecting to: controller => "users" ,: action => "show". Sort of:

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

You may need to additionally perform serialization / deserialization to populate / use session [: question]. I did not try to compile, so I'm not sure.

All this is necessary because when you redirect to the processing of a user’s request, the user browser receives the redirection status code from your server and goes to another page, sending you a new request (which gets into the path and ultimately the controller / action to which you redirected). So, as soon as you return from processing the request, all your variables will be lost. For the next query, you start from scratch.

The render :action => "show" approach (which was in the original scaffold and which you commented out) worked because you didn’t return back to the user, but simply displayed a template with a specific name using variables that you already had in place (in including @question, on which "save" was called and failed, and so an internal check was called and populated the error object).

Actually, it reminded me that you can use a different approach. Instead of passing parameters through the [] session and redirecting to the UserController, you can fill in all the necessary variables and simply visualize the view from this controller. As below:

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

First, the reason that using redirect_to instead of render does not repopulate the form is because when you redirect_to , the controller logic for the action is triggered, while using render ignores the controller logic.

So, when you render :action => 'show' (the default behavior), it displays show.html.erb , with @question set as follows:

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

When you redirect_to current_user , it displays show.html.erb using @question using the code in your show action:

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

This is why you get a new (empty) form, not a pre-filled one.

Is it really important that you use redirect_to ? If so, you need to get the show method to verify. For example, you can rewrite your show method to something like:

 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 

and then make your form on this page with something like:

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

(depending on how your routes are configured and named). Of course, at this point it all becomes terribly non-RESTful, a bit of a mess, and definitely not a Rails way to do something. (Another, worst-case scenario would be to redirect back and pass the parameters through the receive request.) In my opinion, you lose a lot for a small gain, and I'm not sure that I really recommend it.

+1
source

All Articles