Reputation: 13
I have an MainPagesController index page that is rendering the 'new' page from QuotesController that has a form. How do I render the MainPagesController index page with the errors of the form?
MainPages/index
<h1>Welcome to Book Quotes</h1>
<p>
Post your favourite quotes from your favourite books
<%= render 'quotes/new' %>
</p>
<%= render 'quotes/all_quotes' %>
Quotes/new
<h1>Add a quote</h1>
<%= render 'quotes/form' %>
Quotes/_form
<%= form_for @quote do |f| %>
<% if @quote.errors.any? %>
<ul>
<% @quote.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<p>
<%= f.label :passage %><br>
<%= f.text_field :passage %>
</p>
<p>
<%= f.label :book_title %><br>
<%= f.text_field :book_title %>
</p>
<p>
<%= f.label :book_author %><br>
<%= f.text_field :book_author %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
QuotesController
def create
@quote = Quote.new(quote_params)
if @quote.save
redirect_to root_url
else
render #not sure what goes here
end
end
Upvotes: 0
Views: 4214
Reputation: 7532
Since the form that you're dealing with is a nested form, the standard advice of render :new
won't help you here. Instead, you could redirect the user back to the index page, passing the errors via the flash, and update your view to handle displaying those errors.
(Just a thought: it might be worth looking into making this action powered by AJAX. The user experience might be nicer, and it simplifies your code design.)
Anyway, in your QuotesController, the #create
action needs to note the errors and pass them along as it redirects the user back to where they came from:
def create
@quote = Quote.new(quote_params)
if @quote.save
redirect_to root_url
else
flash[:quote_errors] = @quote.errors.full_messages
redirect_to :back # or main_pages_path
end
end
Then, your Quotes/_form view needs to handle those errors:
<%= form_for @quote do |f| %>
<% if flash[:quote_errors] %>
<ul>
<% flash[:quote_errors].each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
# ...
Now, this is a bit ugly. You might be wondering -- couldn't we just pass the @quote
object back via the flash, so the view doesn't have to change? But while that's technically possible, serializing objects into session is a dangerous path to take. I'd suggest avoiding it.
One other option would be to make the quote submission an action not on QuotesController, but on your MainPages controller. E.g.,
class MainPagesController < ApplicationController
def index
# ...
end
def create_quote
@quote = Quote.new(quote_params) # need to move quote_params in, too
if @quote.save
redirect_to root_url
else
render :index
end
end
# ...
This allows the @quote
instance variable to be accessible from your form, so the error handling as-is will work just fine. It's not very RESTful, but then again, neither are most front-end website flows.
Upvotes: 3