Todd Perkins
Todd Perkins

Reputation: 11

Ruby on Rails nested form remembering submitted data and error messages

I'm having a problem with something that seems like it should use the rails magic on this form. I have an articles controller that has a nested resource comments. I have the comment form on the articles#show page. When I submit the form with invalid data, I want to have access to the error object to flag errors, and I also want to remember what the user entered on the form in the event that the form submission is invalid. Currently I am just redirecting back to the article path (which is what's losing the form data / errors I believe).

The form currently submits and will remember the data if its a valid comment submission. Just no errors / remembering of field values.

routes.rb

Rails.application.routes.draw do
  
  root "articles#index"
  
  resources :articles do
    resources :comments
  end
  
end

articles#show

def show
  @article = Article.find(params[:id])
  @comment = Comment.new
end

comments#create

def create
  @article = Article.find(params[:article_id])
  @comment = @article.comments.build(comment_params)

  if @comment.save
    redirect_to article_path(@article)
  else
    # Thinking this should be a render method
    redirect_to article_path(@article)
  end
end

Comment form:

<%= form_with model: [ @article, @comment ], html: { class: "comment-form" } do |form| %>
  <div class="form-set">
    <%= form.label :commenter %><br>
    <%= form.text_field :commenter, class: "commenter" %>
  </div>

  <div class="form-set">
    <%= form.label :body %><br>
    <%= form.text_area :body %>
  </div>

  <div>
    <%= form.submit class: "btn btn-large btn-success" %>
  </div>
<% end %>

Thank you very much in advance for taking the time to look at this!

Currently I am just redirecting back to the article path (which is what's losing the form data / errors I believe). I'm expecting the form to remember form data that was submitted when the submission is invalid, as well as the ability to show errors.

Upvotes: 0

Views: 75

Answers (1)

user229044
user229044

Reputation: 239240

The bog-standard, idiomatic Rails solution here is that, on error, you should just re-render the new view instead of redirecting.

Your action should look like this:

def create
  @article = Article.find(params[:article_id])
  @comment = @article.comments.build(comment_params)

  if @comment.save
    redirect_to article_path(@article)
  else
    render 'new' # no: redirect_to article_path(@article)
  end
end

That's really all there is to it. The new view should be written in such a way that it will use values populated within the model to render the form, which you get for free if you're using form_with model: @article. You may need to decorate the form with error messages, and you may choose to show some kind of "top-level" error message above the form, something like:

<% if @article.errors.any? %>
  <p class="error">Your submission contained one or more errors</p>
<% end %>

Upvotes: 0

Related Questions