I'm trying to show error messages when creating a new instance of a model in my Rails app when a field doesn't pass validation. For some reason, the errors never actually show up on the website next to the fields like they're supposed to. However, the errors appear in the 'Preview' section of the Network tab of Chrome DevTools. So the errors are generating properly. In the terminal it says that new.html.erb
is rendered but I don't think it actually does? Any help would be greatly appreciated - I haven't found much about this online. I'm using Tailwind CSS for styling the front end if that's helpful.
Here's my code:
occasion.rb
class Occasion < ApplicationRecord
belongs_to :user
has_many :registries
has_many :charities, :through => :registries
validates :occasion_name, presence: true
validates :occasion_date, presence: true
validates :url, presence: true, format: { without: /\s/ }, uniqueness: true
validates_uniqueness_of :user_id
end
occasions_controller.rb
class OccasionsController < ApplicationController
load_and_authorize_resource only: [:new, :create, :edit, :update, :destroy]
def index
@occasions = Occasion.all
end
def show
@occasion = Occasion.where(url: params[:url]).first
end
def new
@occasion = Occasion.new
end
def create
@occasion = Occasion.new(occasion_params)
@occasion.user = current_user
if @occasion.save
respond_to do |format|
format.html { redirect_to new_registry_path }
format.js { render :js => "window.location='#{ new_registry_path }'" }
end
else
render :new
end
end
def edit
@occasion = Occasion.find(params[:id])
end
def update
@occasion = Occasion.find(params[:id])
if @occasion.update(occasion_params)
redirect_to @occasion
return
else
render :edit
end
end
def destroy
@occasion = Occasion.find(params[:id])
@occasion.destroy
redirect_to occasions_path
end
private
def occasion_params
params.require(:occasion).permit(:user_id, :occasion_name, :occasion_date, :url)
end
# user authentication is not required for show
skip_before_action :authenticate_user!, :only => [:show]
end
new.html.erb
<%= form_with model: @occasion do |form| %>
<div class="text-center">
<%= form.label :occasion_name, "Occasion Name", class: "text-red-400 font-semibold px-8" %><br>
<%= form.text_field :occasion_name, class: "rounded w-2/5" %>
<% @occasion.errors.full_messages_for(:occasion_name).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<div class="text-center py-2">
<%= form.label :occasion_date, "Occasion Date", class: "text-red-400 font-semibold px-8" %><br>
<%= form.date_field :occasion_date, type: "date", class: "rounded" %>
<% @occasion.errors.full_messages_for(:occasion_date).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<div class="text-center py-2">
<%= form.label :url, 'URL', class: "text-red-400 font-semibold px-8" %><br>
<%= form.text_field :url, class: "rounded" %>
<% @occasion.errors.full_messages_for(:url).each do |message| %>
<div><%= message %></div>
<% end %>
<em><div class="text-sm">domainname.com/yourURLhere</div></em>
</div>
<div class="text-center py-2">
<%= form.submit occasion.persisted? ? 'Update' : 'Save', class: "rounded-full bg-red-400 text-white px-3" %>
</div>
<% end %>
From the provided information, it looks like the form gets submitted as an AJAX request. Since you're not passing local: false
to the form_with
call, there must be a configuration set to use AJAX form submissions by default.
From the docs,
:local
- By default form submits via typical HTTP requests. Enable remote and unobtrusive XHRs submits withlocal: false
. Remote forms may be enabled by default by settingconfig.action_view.form_with_generates_remote_forms
= true.
Pass local: true
to submit the request via a normal HTTP request.
<%= form_with model: @occasion, local: true do |form| %>
<%#= ... %>
<% end %>