Redirecting and routing Ruby on Rails - ruby-on-rails

I'm still new to Ruby on Rails and I'm currently having a issue with routing and redirecting.
I have two controllers "candidate" and "survey". I'm currently viewing "canidate/editEmail.html"
http://www.otoplusvn.com/TherapistSurvey/candidates/editEmail/2
Once the submit button is clicked, the candidate's method for updating the email is executed:
def updateEmail
#candidate = Candidate.find(params[:id])
respond_to do |format|
if #candidate.update_attributes(params[:candidate])
flash[:notice] = 'Candidate email was successfully updated.'
format.html { redirect_to :controller => "survey", :action => "end" }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #candidate.errors, :status => :unprocessable_entity }
end
end
end
This code will update the Candidate's email in the database and redirect it. I want to redirect it to an html page called end.html.erb that is located under the view/Survey/end.html.erb. However, With the present code it will give me a
Unknown action
No action responded to show. Actions: download and lastPage
where download and lastPage are the only methods in the Survey controller. "end" is not a method defined in the survey_controller.rb, but I assumed that it would automatically jump to the end.html.erb located under views/survey
On my local machine, I'm able to get this to work with this updated code:
format.html { redirect_to :controller => "survey/end" }
But this doesn't work on the site that I loaded the ruby on rail application on. In either case, I think there is probably an easier way to do this and i'm doing this incorrectly.
I think it has to deal with the route.rb file or permission that I'm unaware of when you port a local ruby on rail application to a host.
Normally I would think that if i went directly to the file
http://www.otoplusvn.com/TherapistSurvey/survey/end
I would be able to see the page like I was able on my local machine, but I'm not able to with what I have hosted.
In general, I just want to be able to redirect (jump) to another html page indicating that the email update was done correctly and that the survey is over. This is all triggered by hitting a submit button that result in an update to the database being called an a redirect to another page. The problem being how to do the redirect correctly.
BTW: in my routes.rb I have
map.resources :survey
Any Advice Appreciated. Thanks!
D

You need add all other action you want.
map.resources add only route need by ressources browsing.
So add in collection option your method end in your case
map.resources :survey, :collection => {:end => :get}

Add this to routes.rb
map.resources :survey, :collection => {:end => :get}
Run rake routes from terminal in the route of your application to see your routes.
Use named routes:
redirect_to survey_end_path

Related

How do I define a custom URL for a form confirmation page?

I am creating a basic 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 successful submit of the form, I would like to redirect to a custom '/thanks' page in which I thank users for their interest in the product (and also encourage them to complete a short survey.)
Currently, successful submits are displayed at "/invites/:id/" eg "invites/3" which I do not want since it exposes the number of invites that have been submitted. I would like to instead redirect all successful submits to a "/thanks" page.
I have attempted to research "rails custom URLs" but have not been able to find anything that works. The closest I was able to find was this Stackoverflow post on how to redirect with custom routes but did not fully understand the solution being recommended. I have also tried reading the Rails Guide on Routes but am new to this and did not see anything that I understood to allow for creating a custom URL.
I have placed my thanks message which I would like displayed on successful form submit in "views/invites/show.html.haml"
My Routes file
resources :invites
root :to => 'invites#new'
I tried inserting in routes.rb:
post "/:thanks" => "invites#show", :as => :thanks
But I don't know if this would work or how I would tell the controller to redirect to :thanks
My controller (basically vanilla rails, only relevant actions included here):
def show
#invite = Invite.find(params[:id])
show_path = "/thanks"
respond_to do |format|
format.html # show.html.erb
format.json { render json: #invite }
end
end
# GET /invites/new
# GET /invites/new.json
def new
#invite = Invite.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #invite }
end
end
# POST /invites
# POST /invites.json
def create
#invite = Invite.new(params[:invite])
respond_to do |format|
if #invite.save
format.html { redirect_to #invite }
#format.js { render :action => 'create_success' }
format.json { render json: #invite, status: :created, location: #invite }
else
format.html { render action: "new" }
#format.js { render :action => 'create_fail' }
format.json { render json: #invite.errors, status: :unprocessable_entity }
end
end
end
It would seem as if creating a standard URL for displaying a confirmation would be relatively straightforward. Any advice on how to achieve this would be appreciated.
I guess you want to redirect after your create action, which is executed when the form is submitted.
Just add redirect_to in the following way:
def create
#invite = Invite.new(params[:invite])
if #invite.save
...
redirect_to '/thanks'
else
...
redirect_to new_invite_path # if you want to return to the form submission page on error
end
end
I omitted some of the code for brevity.
In your routes add:
get '/thanks', to: "invites#thanks"
Add the thanks action to your invites controller:
def thanks
# something here if needed
end
And create a thanks.html.erb page in app/views/invites.
I would do get "/thanks" => "invites#thanks" in routes.rb and then add this in your controller:
def thanks
end
Then add a file app/views/invites/thanks.html.erb with your thank-you content.
You could create a route like this:
resources :invites do
collection do
get 'thanks'
end
end
This will also create a path helper called thanks_invites_path.
It will be at the invites/thanks path, but if you want it to be on/thanks, you could just do as Jason mentioned:
get "/thanks" => "invites#thanks", :as => :thanks
The as part will generate a helper to access that page: thanks_path.
You would need a extra action in the controller called thanks, and put whatever info you need inside, and also you will need a additional view called thanks.html.erb
Since you want everybody to go to that page after a successful submit, in your create action you would have:
format.html { redirect_to thanks_invites_path} (or thanks_path), what ever you choose, when you name the route you can check it with rake routes if it's okay, and whatever rake routes says, just add _path at the end.

Rails validation conditional redirect

I am currently having an issue with how Rails is performing and responding to a validation result. I have a user registration form. The user could hit this form in two different places. They could hit the form from the homepage or from users/new. Both forms will post to the same place as I am trying to keep it DRY.
The users/new page works as is expected. If the user has a validation issue it will return and populate the form. Where I get a problem is on the home page. If a user has a validation issue it now redirects to the users/new page. I would much prefer that when on the home page I would return the user to that same page and show the validation results there. Is there a way in the controller to redirect to the form the user was at?
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to(#user, :notice => 'User was successfully created.') }
format.xml { render :xml => #user, :status => :created, :location => #user }
else
format.html { render :action => "new" } # I'm thinking I can do something here?
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
I have tried to change the render :action => 'new' line to redirect to the user url but it hasn't worked. Is there something I'm missing?
First, I would add querystring parameters to the URL it is posting to with the controller and action that it came from with something like this:
# Using form_tag
<%= form_tag user_path(#user, :controller_name => controller.controller_name, :action_name => controller.action_name) do %>
# Using form_for
<%= form_for #user, :url => user_path(#user, :controller_name => controller.controller_name, :action_name => controller.action_name) do %>
Then, you can update that line in the create action of your controller like this:
render '#{params[:controller_name]}/#{params[:action_name]}'
Update
I just realized that using the code above, will render the correct view the first time validation fails, but if validation fails a second time, it will try to render the users/create view. If this is the route you want to take, you should not use controller.controller_name, etc in the view, but assign #controller_name correctly and use that variable instead. However, this only adds to the 'overkill' comment made by Xavier.
Art's on the right track, but you can't use a redirect, as you need the instance variable #user that's set in your controller, which'll be lost on a new HTTP request (because ever request is handled by a new, clean controller instance).
But you can use the referer information yourself, and use that to pick the right page to render:
render :action => (request.referer =~ /\/users\/new/)? :new : :index
Note: Another answer popped up while I was posting that suggests adding the old controller / action fields to your form, but that seems like overkill to me - you already have all the information you need in request.referer.
Hope that helps!
Try redirect_to :back
It's a shorthand for redirect_to(request.env["HTTP_REFERER"])
oops, it only works for success. sorry
well, then you have to check inside the block (after format.html) where he came from (by looking at request.env["HTTP_REFERER"]) and render respective action.

2 pages using the same url using rails routes

Im trying make a login page for my rails application that looks like "www.domain.com" and when you login you still are still located at the domain "www.domain.com". Is there a way that I can map 2 different actions to the same url using routes. Twitter does it this way, you log in at twitter.com and after you are logged in you are still located at twitter.com.
You can't do this by simply modifying the routes, but you can do some kind of conditional statement in your controller.
def index
if logged_in
render :action => 'show'
else
render :action => 'new'
end
end
def show
...
end
def new
...
end
There are going to be numerous ways to do this, of course.
After successful login redirect to the root URL.
routes.rb
map.resources :landings
# let's assume that, home page corresponds to landings/index
map.root :controller => "landings", :action => "index"
UserSessionsController
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
redirect_to root_url
else
render :action => :new
end
end

How to modify the create & update method in RoR?

I know that the after the create or update methods is done, they have the method like this
respond_to do |format|
format.js
end
Since I change my form from remote form to non remote form, so I won't use the format.js anymore, I just want to refresh the page, after the user create/update a product, so I have this code:
respond_to do |format|
page.reload
end
But it don't work, so I try not to use respond_to do, I only have the page.reload. But it also show me the site like this:
http://localhost:3000/products/50
I just want to reload the page after I create/update, why I can't do it in this way?
The reload method reloads the browser's current location using JavaScript. I would suggest that you probably want to do a server-side redirect after creating or updating your resource. Something like one of these alternatives:
redirect_to product_path(#product) # Redirect to the 'show' page for the product
redirect_to products_path # Redirect to the products' index page
How can I assign the product_path? in routes.rb?
in routes.db you can either:
map.product 'products/:id', :controller => 'products', :action => 'view'
map.resources :product
map.resource :product
1) will give you product_path(123) and product_url
2) will give you product_path, new_product_path, edit_product_path and so on
HTH

How do I use redirect_to if I've got multiple controllers in different subdirectories?

I've created a small application to learn RoR. (Book database) It consists of a read-only area and a read-write admin area.
After I've got the admin functionality working first, I've moved the controller into a subdirectory and created the read-only controller.
Now when I'm updating a book in the admin area, the redirect_to function redirects to the read-only area.
What am I missing?
Here's the code I'm using:
class Admin::BooksController < ApplicationController
<snip>
def update
#book = Book.find params[:id]
respond_to do |format|
if #book.update_attributes params[:book]
flash[:notice] = "Book updated"
format.html { redirect_to #book }
format.xml { head :ok }
else
<snip>
end
end
end
<snip>
end
This update itself works but it redirects me to /books/1, but I'd want it to redirect to /admin/books/1. I could just hardcode the correct path, but I guess that's not very good style.
What would be the proper way?
PS: Please comment if you need further information.
You are telling it to redirect to book because you are using rails' built in magical recognition of what it should do with the #book object (which is build a url to show the book using the book controller.
format.html { redirect_to #book }
If you want it to go elsewhere you need to be explicit about where you want it to go using a hash for url_for
format.html { redirect_to :controller => 'admin/book', :action => 'show', :id => #book }
or use the paths like klew points out.
so for more detail -
redirect_to (#book) or
redirect_to book_path(#book)
are both shortcuts for this:
redirect_to :controller => book, :action => 'show', :id => #book.id
Rails creates for you url helpers based on your routes.rb. If you have namespace then you can use this:
admin_book_path(#book) # admin/books/2
admin_books_path # admin/books
edit_admin_book_path(#book) # admin/books/2/edit
and so on.
The other way is to use resource_controller it creates for you controller automaticaly and provides some ways to modify it if it's needed. It also gives you some useful url helpers
collection_path # admin/books
object_path # admin/books/2
When you use above helpers in views, than it generates url with namespace if you are in one, or without namespace otherwise.
resource_controller isn't perfect, but in most cases it works good and saves a lot of work.
You can also pass an array to redirect where the first element is a symbol representing the namespace, and the second the element the object.
redirect_to [:admin_book, #book]
You can also use this for form_for, link_to and any other helpers that require a path.

Resources