How to Show Error Message on Rails Views

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:

  1. 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 or rails 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.


  1. 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, the params hash will contain the data you submitted in your form. Ie. params[:email] might be foo@bar.com in your controller. You can test this by adding puts params to your controller action and checking the server logs after you hit the corresponding route.

  2. 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

  1. 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.


  1. 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 the new.html.erb files using any of the approaches mentioned in the RailsGuide. debug(@user) is one option.

  2. 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 a hello world.

  3. 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



Leave a reply



Submit