Reputation: 1051
(I've broken out the 2nd question that originally was part of this post into a separate post)
I am creating a product landing page with Rails in which users can enter their email address to be notified when the product launches. (Yes, there are services/gems etc that could do this for me, but I am new to programming and want to build it myself to learn rails.)
On submit of the form, if there are errors, the app currently redirects to '/invites' I would like to instead display error messages on the same page/URL as the original form? (In my case, the form is located at root while the error messages are displaying at '/invites')
I have read the Rails Guide on Routes and numerous stackoverflow posts on handling form errors nothing I've found seems to answer the question I have.
Update: Based on the reply from @rovermicrover I would like to clarify that, while I'm open to an Ajax solution, I'm fine with a page refresh that displays the error message. (I was not able to get the recommendation by @rovermicrover to function as desired - see my response to that solution below for more details.)
What I did:
Invite model:
class Invite < ActiveRecord::Base
attr_accessible :email
validates :email, :presence => {:message => "Please enter an email address."}
end
My routes file:
SuggestionBoxApp::Application.routes.draw do
root to: 'invites#new'
resources :invites
end
This is what I have in the Invites controller (I've only included the actions I'm referencing: new, create, show - it's basically the default of what Rails might generate):
class InvitesController < ApplicationController
def show
@invite = Invite.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @invite }
end
end
def new
@invite = Invite.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @invite }
end
end
def create
@invite = Invite.new(params[:invite])
respond_to do |format|
if @invite.save
format.html { redirect_to @invite }
format.json { render json: @invite, status: :created, location: @invite }
else
format.html { render action: "new" }
format.json { render json: @invite.errors, status: :unprocessable_entity }
end
end
end
end
Please let me know if there is any additional info I can provide in helping to answer this question. Thanks!
Upvotes: 0
Views: 1175
Reputation: 21
There is a way to do this without resorting the making the form submit "remote", from a pure Ruby on Rails perspective. However, you can do this only if the browser has enabled cookies.
The idea is to save the form data in the session information in case of an error. Just remember to delete the session data in case of success.
def new
@invite = Invite.new(session[:invite])
respond_to do |format|
format.html # new.html.erb
format.json { render json: @invite }
end
end
def create
@invite = Invite.new(params[:invite])
respond_to do |format|
if @invite.save
session.delete(:invite)
format.html { redirect_to @invite }
format.json { render json: @invite, status: :created, location: @invite }
else
session[:invite] = params[:invite]
format.html { render action: "new" }
format.json { render json: @invite.errors, status: :unprocessable_entity }
end
end
end
Upvotes: 0
Reputation: 1453
Make the form 'remote'
form_for @invite, :remote => true
....
Then in the controller
def create
@invite = Invite.new(params[:invite])
respond_to do |format|
if @invite.save
format.html { redirect_to @invite }
format.js { render :action => 'create_suc'}
else
format.html { render action: "new" }
format.js { render :action => 'create_fail' }
end
end
end
/invites/create_suc.js.erb
$('#errors').remove()
$('#new_invite').prepend("<div class='Thanks'>Thanks for signing up</div>")
$('#new_invite').hide("")
/invites/create_fail.js.erb
$('#new_invite').html('<%= escape_javascript render("form", :invite => @invite) %>');
Forms is a partial with your.... form in it, and also the handling of all errors on @invite.
Upvotes: 2