Validation Errors Not Showing in Views
I have an app where I got the CRUD functionality working and I added some AJAX to learn how to use it. I changed a class to use AJAX for the delete, edit and show views from the index view. That worked good, until I noticed that both the edit and new views had a problem. If a required field is left out, the validations don't warn the user of the missing fields. It just seems to do nothing until the users guesses the missing required fields (in which case it creates and updates just fine).
Both the edit and new views are using the same partial form. So that has been the center of my attention to debug this. Been working on it for days and I just can't get it. Currently, I'm just focused on the new view because that isn't using AJAX at all (I figure there's less moving parts to trip over).
I've been posting on other forums for days and nobody's even commented, please help.
This is the controller:
require 'drinks'
class CocktailsController < ApplicationController
before_action :authenticate_user!
before_action :set_cocktail, only: %i[ show edit update destroy ]
# GET /cocktails or /cocktails.json
def index
@cocktails = set_cocktail_sort.paginate(page: params[:page], per_page: 16)
render :index
end
# GET /cocktails/1 or /cocktails/1.json
def show
respond_to do |format|
format.js
format.html
end
render :show
end
# GET /cocktails/new
def new
@cocktail = Cocktail.new
respond_to do |format|
format.js
format.html
end
render :new
end
# GET /cocktails/1/edit
def edit
respond_to do |format|
format.js
format.html
end
render :edit
end
# POST /cocktails or /cocktails.json
def create
@cocktail = current_user.cocktails.build(cocktail_params)
if !@cocktail.api_image_url.nil?
Cocktail.capture_api_image(@cocktail)
else
@cocktail.cocktail_photo.attach(params[:cocktail][:cocktail_photo])
end
if @cocktail.save
redirect_to @cocktail, alert: "Cocktail was successfully created."
else
render :new
end
end
# PATCH/PUT /cocktails/1 or /cocktails/1.json
def update
respond_to do |format|
if @cocktail.update!(cocktail_params)
if params[:cocktail][:cocktail_photo].present?
@cocktail.cocktail_photo.purge
@cocktail.cocktail_photo.attach(params[:cocktail][:cocktail_photo])
end
format.js { redirect_to @cocktail, notice: "Cocktail was successfully updated." }
format.html { redirect_to @cocktail, notice: "Cocktail was successfully updated." }
format.json { render :show, status: :ok, location: @cocktail }
else
format.js { render :edit, status: :unprocessable_entity }
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @cocktail.errors, status: :unprocessable_entity }
end
end
end
# DELETE /cocktails/1 or /cocktails/1.json
def destroy
@cocktail.destroy
respond_to do |format|
format.js { redirect_to cocktails_url, notice: "Cocktail was successfully removed." }
format.html { redirect_to cocktails_url, notice: "Cocktail was successfully removed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cocktail
@cocktail = Cocktail.find(params[:id])
end
def set_cocktail_sort
@cocktails_sort = current_user.cocktails.order('name ASC')
end
# Only allow a list of trusted parameters through.
def cocktail_params
params.require(:cocktail).permit(
:name,
:category,
:alcoholic,
:glass,
:instructions,
:ingredient1,
:ingredient2,
:ingredient3,
:ingredient4,
:ingredient5,
:ingredient6,
:ingredient7,
:ingredient8,
:ingredient9,
:ingredient10,
:ingredient11,
:ingredient12,
:ingredient13,
:ingredient14,
:ingredient15,
:measure1,
:measure2,
:measure3,
:measure4,
:measure5,
:measure6,
:measure7,
:measure8,
:measure9,
:measure10,
:measure11,
:measure12,
:measure13,
:measure14,
:measure15,
:api_id_drink,
:api_image_url)
end
end
This is the form partial:
<% if @cocktail.errors.any? %>
Please fix these errors:
- <%= message %>
<% @cocktail.errors.full_messages.each do |message| %>
<% end %>
<% end %>
Measures & Ingredients
<%= form.label :instructions %>
This is the new view (I'll leave out the edit view for simplicity):
New Cocktail
This is the model:
require 'uri'
require 'open-uri'
class Cocktail < ApplicationRecord
belongs_to :user
has_one_attached :cocktail_photo
validates :name, presence: true
validates :instructions, presence: true
validates :ingredient1, presence: true
validates_length_of :name, maximum: 50
validates_length_of :instructions, maximum: 500
validates_length_of :ingredient1, maximum: 50
validates_length_of :measure1, maximum: 30
def self.capture_api_image(cocktail)
filename = File.basename(URI.parse(cocktail.api_image_url).path)
file = URI.open(cocktail.api_image_url)
cocktail.cocktail_photo.attach(io: file, filename: filename, content_type: 'image/jpg')
end
end
When I look in terminal running the rails server, I see the params passing to ActiveRecord, the reference back to the controller and a big red ROLLBACK. Then another controller reference and then it renders the new view. here is the tail end of it:
↳ /home/drew/.rvm/gems/ruby-2.6.5/gems/activerecord-5.2.6/lib/active_record/log_subscriber.rb:98
(0.4ms) BEGIN
↳ app/controllers/cocktails_controller.rb:53
(0.4ms) ROLLBACK
↳ app/controllers/cocktails_controller.rb:53
Rendering cocktails/new.html.erb within layouts/application
Rendered cocktails/_cocktail_image.html.erb (5.9ms)
Rendered cocktails/_form.html.erb (14.0ms)
Rendered cocktails/new.html.erb within layouts/application (39.5ms)
Rendered layouts/_logo.html.erb (0.9ms)
Rendered layouts/_header-nav.html.erb (3.8ms)
Completed 200 OK in 121ms (Views: 102.9ms | ActiveRecord: 1.6ms)