steveks17
steveks17

Reputation: 73

Rails Validation Errors not being displayed

For some reason my validation errors are being picked up but are not displaying on the page as I would like below is my model and the new view. I will also attach a picture of my validation error being picked up but not displaying in the view.

Model

class Review < ApplicationRecord
  belongs_to :user
  belongs_to :tea

  validates :title, presence: true
  validates :rating, numericality: {only_integer: true, greater_than_or_equal_to: 0, less_than: 11}
  validates :tea, uniqueness: {scope: :user, message: "has already been reviewed by you" }

  scope :order_by_rating, ->{group(:id).order('avg(reviews.rating) desc')}
end
View
<h1>Write a Review for  </h1>

<%= form_for Review.new do |f|%>
    <% if @review.errors.any? %>
        <h2>Errors:</h2>
        <ul>    
            <% @review.errors.full_messages.each do |message| %>
            <li><%= message %></li>
           <% end %> 
        </ul>
    <% end %>

Validation Error

Upvotes: 0

Views: 632

Answers (3)

steveks17
steveks17

Reputation: 73

.save! was not allowing the view to render errors as shown adjusting create method allows errors to be displayed.

The main reason for this is the rails bang (!) methods are used to raise errors rather than just handling and passing it.

Upvotes: 0

max
max

Reputation: 101811

In Ruby there is a convention that methods ending with ! denote a "dangerous" method. The method either mutates its receiver or raises an exception. ActiveRecord::Persistence has both normal and "dangerous" methods:

  • save and save!
  • create and create!
  • update and update!

The later raises an ActiveRecord::RecordInvalid exception if any of the validations fail. This is really useful when you're creating records from a seed file, in your tests or inside a transaction.

But when you are normally handling user input you want to use the normal save method as invalid input is just a fact of life and not an exceptional event. If you rely on changing the code to .save! for debugging you should really learn to use pry or byebug instead to step into the code.

You should also fix the form so that you're binding it to the @review instance variable so that the users input is not erased. Nobody likes badly implemented forms that makes them retype everything.

<%= form_for @review.new do |f|%>
  # ...
<% end %>

Upvotes: 2

sevensidedmarble
sevensidedmarble

Reputation: 683

You aren't getting errors on the object because you're calling a version of save that raises exceptions.

Check out the documentation on #save! vs #save: https://apidock.com/rails/ActiveRecord/Base/save%21

This isn't a great place to use #save! instead, you should do things with #save like:

if @review.save
  # redirect
else
  # You can now access the `#errors` method if you want
  errors = @review.errors
end

Read this for more info on ActiveRecord error handling: https://api.rubyonrails.org/classes/ActiveModel/Errors.html

Upvotes: 0

Related Questions