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!
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With