Reputation: 61
We have a form to submit ratings for a certain restaurant in a in our views/restaurants/show.html.erb. If there is a validation error we get redirected back to views/restaurants/show.html.erb but the validation messages do not appear. We figured out that this happens because we lose the messages using redirect_to(@restaurant) in our RatingController create action. But how can we get back without redirection?
Thanks!
Upvotes: 5
Views: 5278
Reputation: 927
Here is how I did it still doing the redirect:
Just before you redirect on validation errors in your controller store errors to flash like suggested by @shingara:
if @restaurant_rating.save
redirect_to @restaurant, :notice => "Successfully added rating to restaurant."
else
flash[:error] = @restaurant_rating.errors
redirect_to @restaurant, :alert => "There were errors to add rating to restaurant. "
end
Then in your form for rating you assign errors back for the rating object just before rendering the form:
- flash[:error].messages.each {|error| @restaurant_rating.errors.add(error[0], error[1][0]) } if flash[:error]
= simple_form_for @restaurant_rating do |f|
....
Upvotes: 2
Reputation: 19505
Here is how I solved this. (Note that in what follows I'm obviously just including just the most relevant lines.)
In the model there may be multiple validations and even methods that potentially report on multiple errors.
class Order < ActiveRecord::Base
validates :name, :phone, :email, :presence => true
def some_method(arg)
errors.add(:base, "An error message.")
errors.add(:base, "Another error message.")
end
end
As well, the controller action may set flash messages. Finally, the user may have entered data into the input fields, and we want it to persist through the redirect_to
too.
class OrdersController < ApplicationController
def create
@order = Order.new(params[:order])
respond_to do |format|
if @order.save
session.delete(:order) # Since it has just been saved.
else
session[:order] = params[:order] # Persisting the order data.
flash[:notice] = "Woohoo notice!" # You may have a few flash messages
flash[:alert] = "Woohoo alert!" # as long as they are unique,
flash[:foobar] = "Woohoo foobar!" # since flash works like a hash.
flash[:error] = @order.errors.to_a # <-- note this line
format.html { redirect_to some_path }
end
end
end
end
Depending on your setup, you may or may not need to save the model data, such as order, to the session. I did this for the purpose of passing the data back to the original controller, and thereby being able to setup the order there again.
In any case, to display the actual error and flash messages, I did the following (in views/shared/_flash_messages.html.erb
, but you could do it in application.html.erb
or wherever else makes sense for your app). And this is thanks to that line flash[:error] = @order.errors.to_a
<div id="flash_messages">
<% flash.each do |key, value|
# examples of value:
# Woohoo notice!
# ["The server is on fire."]
# ["An error message.", "Another error message."]
# ["Name can't be blank", "Phone can't be blank", "Email can't be blank"]
if value.class == String # regular flash notices, alerts, etc. will be strings
value = [value]
end
value.each do |value| %>
<%= content_tag(:p, value, :class => "flash #{key}") unless value.empty? %>
<% end %>
<% end %>
</div><!-- flash_messages -->
To be clear, regular flash messages such as notices, alerts, etc. will be strings, however errors will be arrays since the above call was errors.to_a
Upvotes: 4
Reputation: 18765
After your clarification in the comment, you need to setup your
/app/views/layouts/application.html.erb
with this line
<%- flash.each do |name, msg| -%><%= content_tag :div, msg, :id => "flash_#{name}" %><%- end -%>
Upvotes: 0
Reputation: 83680
You can use render
instead of redirect_to
render :action => "show"
or set flash[:error]
, flash[:notice]
again, because they automatically reseted
Upvotes: 1
Reputation: 46914
You can pass your error on flash message
flash[:error] = @restaurant.errors
After you need display it in your redirect
Upvotes: 2