Reputation: 73
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 %>
Upvotes: 0
Views: 632
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
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
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