How to show error message on rails views?
The key is that you are using a model form, a form that displays the attributes for an instance of an ActiveRecord model. The create action of the controller will take care of some validation (and you can add more validation).
Controller re-renders new
View when model fails to save
Change your controller like below:
def new
@simulation = Simulation.new
end
def create
@simulation = Simulation.new(simulation_params)
if @simulation.save
redirect_to action: 'index'
else
render 'new'
end
end
When the model instance fails to save (@simulation.save
returns false
), then the new
view is re-rendered.
new
View displays error messages from the model that failed to save
Then within your new
view, if there exists an error, you can print them all like below.
<%= form_for @simulation, as: :simulation, url: simulations_path do |f| %>
<% if @simulation.errors.any? %>
<ul>
<% @simulation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<div class="form-group">
<%= f.label :Row %>
<div class="row">
<div class="col-sm-2">
<%= f.text_field :row, class: 'form-control' %>
</div>
</div>
</div>
<% end %>
The important part here is that you're checking whether the model instance has any errors and then printing them out:
<% if @simulation.errors.any? %>
<%= @simulation.errors.full_messages %>
<% end %>
Rails 5 - Displaying error messages
The issue was that in order to make the @user
instance variable available to the view, you need to render rather than redirect.
When you redirect, you're sending a response to the user that says, "Hit me up again". When the subsequent request comes in, the action gets executed a second time. The @user
instance variable was available the first time the action was executed, but based on the logic in the action, doesn't get populated with errors on the second time (why would it).
See How are Rails instance variables passed to views?.
The issue could be at any of the following steps:
- The request may not be getting routed to the controller you expect. Try looking at the server logs. When you start your server with
rails server
orrails s
in the console, that window will show all incoming requests, and it'll show the controller + action that get hit. For example:
Example from my test app:
code/blog [master●] » rails s
=> Booting Puma
=> Rails 5.0.2 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.8.2 (ruby 2.4.1-p111), codename: Sassy Salamander
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
Started GET "/" for ::1 at 2017-04-19 17:55:42 -0700
ActiveRecord::SchemaMigration Load (0.4ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by UncategorizedPagesController#home as HTML
Rendering uncategorized_pages/home.html.erb within layouts/application
Rendered uncategorized_pages/home.html.erb within layouts/application (1.4ms)
Rendered partials/_navbar.html.erb (0.8ms)
Completed 200 OK in 293ms (Views: 291.3ms | ActiveRecord: 0.0ms)
Here you can see that the request is GET /
, and it hits the home
action of UncategorizedPagesController
. To be doubly sure, you could add a puts "hits this action"
in your controller action, and look for "hits this action" in your server logs.
The form(s) may not be sending the payload you expect them to be sending to the server. Try checking the
params
hash in your controller. As the link explains, theparams
hash will contain the data you submitted in your form. Ie.params[:email]
might befoo@bar.com
in your controller. You can test this by addingputs params
to your controller action and checking the server logs after you hit the corresponding route.The validations may not be behaving as you expect them to. To test this, try using the console (in sandbox mode so it doesn't mess with your actual database) like so:
Console output:
$ rails console --sandbox
>> user = User.new(name: "", email: "mhartl@example.com")
>> user.valid?
=> false
>> user.errors.full_messages
=> ["Name can't be blank"]
You should also use unit tests to make sure your validations work as expected. See below for an example from the Rails Tutorial
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "user@example.com")
end
test "should be valid" do
assert @user.valid?
end
test "name should be present" do
@user.name = ""
assert_not @user.valid?
end
test "email should be present" do
@user.email = " "
assert_not @user.valid?
end
end
- You may not be trigging validation to happen. From the official RailsGuide:
The following methods trigger validations, and will save the object to
the database only if the object is valid:
- create
- create!
- save
- save!
- update
- update!
The bang versions (e.g.
save!) raise an exception if the record is invalid. The non-bang
versions don't: save and update return false, and create just returns
the object.
Your controller logic may not be sending the user with errors back to the view. To test this, print out the full
@user
in one of thenew.html.erb
files using any of the approaches mentioned in the RailsGuide.debug(@user)
is one option.You may not be referencing the right file in your attempt to render the
_errors.html.erb
partial. To test this, try to render the partial with just ahello world
.You may not be passing in the object to the partial properly. To test this, try logging out your object from the view using any of the approaches mentioned in the RailsGuide.
debug(object)
is one option.
It seems that you are doing it properly though. From the docs:
If you're not going to be using any of the options like collections or layouts, you can also use the short-hand defaults of render to render partials. Examples:
# Instead of <%= render partial: "account", locals: { account: @buyer } %>
<%= render "account", account: @buyer %>
How to render error messages in views in Rails?
The root cause is the @order
instance variable is not being carried through the redirection process, so that's the reason you don't see any error messages.
You can put the error messages into flash
container
if @order.save
[do something]
else
flash[:order_errors] = @order.errors.full_messages
redirect_to :back
end
<% if flash[:order_error] %>
[display it here]
<% end %>
Validation error messages not showing in form view
instead of redirect_to new_user_property_path
in else
block, you should
render 'new'
Reason: redirect
instructs the browser to make the new request, because of which you end up loosing the context of @property
object with it's errors. It actually makes a fresh request to new
action. render
will continue with the current action (which is create
in this case) and render the response in new
view with @property
, errors and previous form body.
Rails 7 signup form doesn't show error messages
If you look at the logs you can see that Rails is getting an AJAX request in the form of a turbo stream:
Processing by UsersController#create as TURBO_STREAM
Where it should read:
Processing by UsersController#create as HTML
To disable turbo you want need to set a data-turbo="false"
attribute on the form:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @user, data: { turbo: false }) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
The local: false
option only works with the old Rails UJS javascript library which was the default prior to Rails 7. You can also disable Turbo by default with:
import { Turbo } from "@hotwired/turbo-rails"
Turbo.session.drive = false
See:
https://turbo.hotwired.dev/handbook/drive#disabling-turbo-drive-on-specific-links-or-forms
Rails error messages not showing?
You are not seeing any error messages because all the forms generated by form_with
tag are remote: true
by default and send xhr(ajax) requests to the server. If you want to see the error messages, as of your current setup, you have to add local: true
wich makes the submission normal.
Replacing
<%= form_with model: @seed, class: "form-horizontal" do |f| %>
with
<%= form_with model: @seed, local: true, class: "form-horizontal" do |f| %>
will do the trick. Hope this will help.
Related Topics
You Don't Have Write Permissions into the /Var/Lib/Gems/1.9.1 Directory
Suppresing Output to Console with Ruby
Rails - Aciverecord Use :Dependent => :Destroy on Condition
Creating a Test Suite Using Ruby Minitest
Log Doesn't Work in Production with Delayed Job
Error Running Heckle? 'Current_Code': Undefined Method 'Translate' for Ruby2Ruby
Detecting If This Is an Iframe Load or Direct
What Are Some Good Role Authorization Solutions Used with Authlogic
How to Programmatically Check If a Certificate Has Been Revoked
How to Write Bom Marker to a File in Ruby
Recommended Two-Way Encryption Gems for Ruby
Convert Ruby Source Code from Old Style to New Style Hash
Cannot Load Such File -- Rack/Handler/Puma