I've tried looking at other answers for this but I can't seem to figure out why my redirect isn't working.
So I'm using Devise with Rails 3.1, and I'm making a shopping site. Visitors aren't allowed to add things to their cart unless they are signed in. This is what I'm having trouble with: if they aren't signed in, I want to redirect them to the Items index page. Here's what I have:
class ItemsController < ApplicationController
def add_to_cart
#item = Item.find(params[:id])
if current_user
#item.update_attributes(:cart_id => #current_cart.id)
redirect_to :back
else
redirect_to categories_path, notice: 'You must sign in to add an item to your cart.'
end
end
.
.
.
end
As of right now, when I click the link to add to cart, the method gets executed (I can see Rails loading and defining #item in the server log), and it reaches the 'else' statement, but no redirect happens.
I've already generated scaffolding for the index, new, etc. (all the RESTful actions). Also, I'm sure that I'm reaching the add_to_cart method because I've tried debugging with some puts statements. What's happening here?
EDIT:
Also, another weird thing which may be of use... The server seems to try to execute this method twice, and tries to 'get' categories twice:
Started GET "/items/3/add_to_cart" for 127.0.0.1 at 2012-01-12 16:53:11 -0800
Processing by ItemsController#add_to_cart as JS
Parameters: {"id"=>"3"}
Category Load (0.3ms) SELECT "categories".* FROM "categories"
Item Load (0.2ms) SELECT "items".* FROM "items" WHERE "items"."id" = $1 LIMIT 1 [["id", "3"]]
Redirected to http://localhost:3000/categories
Completed 302 Found in 26ms
Started GET "/items/3/add_to_cart" for 127.0.0.1 at 2012-01-12 16:53:11 -0800
Processing by ItemsController#add_to_cart as JS
Parameters: {"id"=>"3"}
Category Load (0.2ms) SELECT "categories".* FROM "categories"
Item Load (0.2ms) SELECT "items".* FROM "items" WHERE "items"."id" = $1 LIMIT 1 [["id", "3"]]
Redirected to http://localhost:3000/categories
Completed 302 Found in 25ms
Started GET "/categories" for 127.0.0.1 at 2012-01-12 16:53:12 -0800
Processing by CategoriesController#index as JS
Category Load (0.2ms) SELECT "categories".* FROM "categories"
CACHE (0.0ms) SELECT "categories".* FROM "categories"
Rendered categories/index.html.erb within layouts/application (0.0ms)
Completed 200 OK in 35ms (Views: 28.5ms | ActiveRecord: 4.2ms)
Started GET "/categories" for 127.0.0.1 at 2012-01-12 16:53:12 -0800
Processing by CategoriesController#index as JS
Category Load (0.2ms) SELECT "categories".* FROM "categories"
CACHE (0.0ms) SELECT "categories".* FROM "categories"
Rendered categories/index.html.erb within layouts/application (0.0ms)
Completed 200 OK in 37ms (Views: 30.6ms | ActiveRecord: 4.2ms)
EDIT 2 (as requested by Delba)
resources :items do
member do
get 'add_to_cart'
end
end
EDIT 3: changing the else statement to respond to javascript
respond_to do |format|
format.js { redirect_to items_path, notice: 'You must sign in to add an item to your cart.' }
end
For anyone who may need answers to this question, simply replace redirect_to statements with the following:
respond_to do |format|
format.js
end
Then, in your views under items, make a add_to_cart.js.erb page, consisting of javascript to make notices, or do whatever. Here's what I put in mine:
alert("Need to be signed in")
EDIT: Also, for the part where it executes twice: this is somewhat unrelated, but for some reason by default Rails includes duplicate Javascripts. Specifically, look at application.js: it says require jquery and require jquery_ujs. Disable one of these and you're home free.
To disable one of these javascripts:
Go to assets/application.js
Remove the comments (the // ) before require jquery, require tree .
This way, Rails doesn't assume the default and instead includes only jquery and whatever other javascripts you have in assets/javascripts
Related
I have a simple photo gallery on a site, and am having some trouble when I invoke either the edit or delete paths. I click on the button and the page acts like it is going to load, then goes to an error page. Here is the trace from the console:
Started GET "/photos/17/edit" for 127.0.0.1 at 2015-10-12 09:41:08 -0700
Started GET "/photos/17/edit" for 127.0.0.1 at 2015-10-12 09:41:08 -0700
Processing by PhotosController#edit as HTML
Processing by PhotosController#edit as HTML
Parameters: {"id"=>"17"}
Parameters: {"id"=>"17"}
Photo Load (0.2ms) SELECT "photos".* FROM "photos" WHERE "photos"."id" = $1 LIMIT 1 [["id", 17]]
Photo Load (0.2ms) SELECT "photos".* FROM "photos" WHERE "photos"."id" = $1 LIMIT 1 [["id", 17]]
Album Load (7.9ms) SELECT "albums".* FROM "albums"
Album Load (7.9ms) SELECT "albums".* FROM "albums"
Rendered photos/_form.haml (35.7ms)
Rendered photos/_form.haml (35.7ms)
Rendered photos/edit.haml within layouts/application (38.9ms)
Rendered photos/edit.haml within layouts/application (38.9ms)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Rendered layouts/_navbar.html.haml (5.0ms)
Rendered layouts/_navbar.html.haml (5.0ms)
Completed 200 OK in 187ms (Views: 174.4ms | ActiveRecord: 9.4ms)
Completed 200 OK in 187ms (Views: 174.4ms | ActiveRecord: 9.4ms)
Then I get this immediately after, before the edit page loads:
Started GET "/undefined" for 127.0.0.1 at 2015-10-12 09:41:08 -0700
Started GET "/undefined" for 127.0.0.1 at 2015-10-12 09:41:08 -0700
ActionController::RoutingError (No route matches [GET] "/undefined"):
I've looked over my controller and methods and haven't seen anything that would suggest the need for it to look for the /undefined path. What is worse is that it doesn't happen every time, which made me think there was something wrong with my ruby installation or something. If that was the case, it would not give the error on Heroku (which it does) and would probably error out in other applications I work on (which it doesn't).
Controller:
def update
respond_to do |format|
if #photo.update(photo_params)
format.html { redirect_to #photo, notice: 'Photo was successfully updated.' }
format.json { render :show, status: :ok, location: #photo }
else
format.html { render :edit }
format.json { render json: #photo.errors, status: :unprocessable_entity }
end
end
end
def destroy
#photo.destroy
respond_to do |format|
format.html { redirect_to photos_path, notice: 'Photo was successfully destroyed.' }
format.json { head :no_content }
end
end
Model:
class Photo < ActiveRecord::Base
mount_uploader :image, ImageUploader
belongs_to :album
validates_presence_of :image
end
When I notice that it is redirecting me, I can just browse to the picture itself fine (photos/8), but the edit path is still kicking me to the /undefined (photos/8/edit).
I realise (and hope) you might have solved this already, but I've been banging my head against the wall due to a similar problem - a GET request to /undefined route. Luckily, I was able to solve it and this might help people with similar problems.
To explain my situation - I have some AJAX calls and I suspected it might have something to do with that, even though I did not build up any URLs with variables that could be undefined.. or so I thought (I was partially right, though).
I was fetching some information (including image URLs to be rendered in view thereafter) based on data returned by an API in JSON format. I hope you see where I am going with this :)
Turns out one image (for that specific API request, I am sure there are other such cases which I haven't yet found) had no URL defined. As I passed the json data to a constructor, I expected the image URL to be defined and inserted that into the image src attribute. The URL was, however, apparently undefined. Therefore, instead of loading the image via absolute path to the API's CDN, as the src had no http(s)://, it tried to load it from local server. As the variable with image url was undefined, the image src attribute pointed to a relative /undefined route. Hence a GET request to "/undefined" route.
I should note that this was not an ajax call per se, the get request was a result of using data from ajax call to construct an image src attribute. The fact that I used that data for constructing a google maps infowindow HTML structure (which included an image in it) only compounded the problem as the missing image (due to undefined src) would only show up after clicking on a specific google maps marker.
So, for your case (while it might not be relevant for you anymore, might be for someone else) - make sure you look at image src attributes as images will start loading immediately after your page (or in case of ajax loading and constructing HTML image tags afterwards) loads. Hence one 'normal' request that gets processed as it should. If, however, an image src attribute is "undefined", it will then immediately start a get request to "/undefined" route.
I am redirecting the user after a model save.
if #client.save
redirect_to :new_course
on the new course controller I have no redirection
def new
#course = Course.new
end
After the course_controller#new is been executed I am been redirected on another controller view.
I can't figure out where does this redirection comes from.
I am tracing the application and seen that
Started GET "/courses/new" for ::1 at 2015-10-01 15:01:46 -0400
Processing by CoursesController#new as */*
Therapist Load (0.6ms) SELECT "therapists".* FROM "therapists" WHERE "therapists"."id" = $1 ORDER BY "therapists"."id" ASC LIMIT 1 [["id", 14]]
Rendered courses/new.html.erb within layouts/application (228.3ms)
Client Exists (0.5ms) SELECT 1 AS one FROM "clients" WHERE "clients"."therapist_id" = $1 LIMIT 1 [["therapist_id", 14]]
Completed 200 OK in 679ms (Views: 652.7ms | ActiveRecord: 3.5ms)
Started GET "/clients/show" for ::1 at 2015-10-01 15:01:46 -0400
Processing by ClientsController#show as HTML
Therapist Load (0.7ms) SELECT "therapists".* FROM "therapists" WHERE "therapists"."id" = $1 ORDER BY "therapists"."id" ASC LIMIT 1 [["id", 14]]
Rendered clients/show.html.erb within layouts/application (0.4ms)
Client Exists (0.4ms) SELECT 1 AS one FROM "clients" WHERE "clients"."therapist_id" = $1 LIMIT 1 [["therapist_id", 14]]
Client Exists (0.3ms) SELECT 1 AS one FROM "clients" WHERE "clients"."therapist_id" = $1 LIMIT 1 [["therapist_id", 14]]
Client Exists (0.2ms) SELECT 1 AS one FROM "clients" WHERE "clients"."therapist_id" = $1 LIMIT 1 [["therapist_id", 14]]
Completed 200 OK in 371ms (Views: 367.8ms | ActiveRecord: 1.6ms)
The redirect_to method sends a response to the browser that indicates it should load a new page. Then Rails is finished and waits for another request, that controller object is destroyed as it's no longer needed.
This is typically done with the Location: header in the HTTP response.
The next request to come in is the result of this redirection.
Rails sets up some default redirects based on common functionality. Basically, after you create a new object it assumes you will want to go view it and redirects to the #show action. If you want it to go somewhere else you need to set up that route.
As I recall there are also instances where rails will default an action you haven't created for instance, if you have an index action in your routes but never set it up rails will make one for you with #my_items = MyItems.all and render the index view.
IMPORTANT NOTE: The id does not matter, it is same in all cases.
I am only seeing the name field, not description, hours, etc even though these aren't null.
I have declared all standard routes through resources (with default format json), not individually.
I have even tried creating a projects/show.json.jbuilder file:
json.name #project.name
json.description #project.description
json.hours #project.hours
json.ownername #project.ownername
My projects/show method:
#project = Project.find(params[:id])
render :json => #project
FIRST EDIT:
I added logger.debug right before defining #project in my show method.
Now in my command prompt window for the local server, I am seeing:
Started GET "/projects/12" for 127.0.0.1 at 2015-02-25 16:36:45 -0500
ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by ProjectsController#show as HTML
Parameters: {"id"=>"12"}
Project Load (0.1ms) SELECT "projects".* FROM "projects" WHERE "projects"."id" = ? LIMIT 1 [["id", 12]]
#<Project:0x007f95477e72f8>
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 51]]
Completed 200 OK in 42ms (Views: 15.2ms | ActiveRecord: 0.9ms)
I am wondering why I am seeing the "User Load" part, since my Project model does not belong to a User object or have any relationship with it (though in the past it may have had before that relationship was removed). Also, I don't think I saw
#<Project:0x007f95477e72f8>
earlier.
I solved my problem this way.
Basically, projects/12.json currently works and not projects/12. Since I am more interested in obtaining the data client side, it is ok for me. I would need a projects/show.html.erb page that calls all the project data through view helper methods, for the HTML to work.
def show
#project = Project.find(params[:id])
respond_to do |format|
format.html
format.json
end
end
projects/12.json works because I have a projects/show.json.jbuilder file (as I shared in my original question post):
json.name #project.name
json.description #project.description
json.hours #project.hours
json.ownername #project.ownername
I have a destroy method within a notecards controller that I am calling from a users page to delete a notecard. In the first example below.. the redirect is passing the notecard ID resulting in a page not found, while the second the user ID is being passed correctly finding the user page.. can someone help me understand why?
Redirects to user passing id of notecard
def destroy
#note = Notecard.find_by_id(params[:id])
delete_note(#note)
redirect_to user_path(#current_user)
end
Redirects to user passing id of user
def destroy
#note = current_user.notecards.find_by_id(params[:id])
delete_note(#note)
redirect_to user_path(#current_user)
end
Update:
Thanks for the responses. The code is here: https://github.com/incorvia/plumnotes/.. The authentication is in the sessions helper and the sessions controller. As for the log:
With Notecard.find_by_id(params[:id])
Started DELETE "/notecards/177" for 127.0.0.1 at 2011-10-15 11:53:38 -0400
Processing by NotecardsController#destroy as HTML
Parameters: {"authenticity_token"=>"WctbONb/qAO+hesHZ6Yw5zU19eCPNGeILIhxnW9Pi1Y=", "id"=>"177"}
Notecard Load (0.3ms) SELECT `notecards`.* FROM `notecards` WHERE `notecards`.`id` = 177 LIMIT 1
SQL (0.8ms) DELETE FROM `notecards` WHERE `notecards`.`id` = 177
Redirected to http://localhost:3000/users/177
Completed 302 Found in 12ms
Started GET "/users/177" for 127.0.0.1 at 2011-10-15 11:53:39 -0400
Processing by UsersController#show as HTML
Parameters: {"id"=>"177"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 9 LIMIT 1
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 177 LIMIT 1
Completed 404 Not Found in 14ms
ActiveRecord::RecordNotFound (Couldn't find User with id=177):
app/controllers/users_controller.rb:11:in `show'
Rendered /Users/Kevin/.rvm/gems/ruby-1.9.2-p290#notes/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.4ms)
Rendered /Users/Kevin/.rvm/gems/ruby-1.9.2-p290#notes/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.0ms)
Rendered /Users/Kevin/.rvm/gems/ruby-1.9.2-p290#notes/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (4.6ms)
With current_user.notecards.find_by_id(params[:id])
Started DELETE "/notecards/179" for 127.0.0.1 at 2011-10-15 11:56:18 -0400
Processing by NotecardsController#destroy as HTML
Parameters: {"authenticity_token"=>"WctbONb/qAO+hesHZ6Yw5zU19eCPNGeILIhxnW9Pi1Y=", "id"=>"179"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 9 LIMIT 1
Notecard Load (0.6ms) SELECT `notecards`.* FROM `notecards` WHERE `notecards`.`user_id` = 9 AND `notecards`.`id` = 179 LIMIT 1
SQL (0.9ms) DELETE FROM `notecards` WHERE `notecards`.`id` = 179
Redirected to http://localhost:3000/users/9
Completed 302 Found in 95ms
Started GET "/users/9" for 127.0.0.1 at 2011-10-15 11:56:18 -0400
Processing by UsersController#show as HTML
Parameters: {"id"=>"9"}
Hard to guess what is defined to local var #current_user and where it occurs.
If you really interested, why, - probably more piece of code could be helpful.
Sometimes, keep it simple could be quite an interesting idea (:
redirect_to user_path( current_user.id )
It seems that #current_user wasn't actually being defined for the #Notcard controller unless the current_user method was called. That's why that the current_user.notecards... worked
It also seems that with user_path(#current_user) .. if #current_user isn't defined then it just takes the id from the params.. which happens to be the notecard id and not a user id...
The solution to fixing it was to either user current_user.notecards.. or add a before_filter for the controller that authorizes users and defines the #current_user instance variable :-)
This is my route:
scope ":username" do
resources :feedbacks
end
So when I go to mydomain.com/test/feedbacks/10 it shows the correct feedback with id=10 that belongs to username=test.
But, if I go to mydomain.com/test2/feedbacks/10 it shows me the same feedback with id=10, which does NOT belong to username=test2.
How do I restrict this from happening?
I am using the Vanity gem to give me the username in the URL, this is what that route looks like:
controller :vanities do
match ':vname' => :show, :via => :get, :constraints => {:vname => /[A-Za-z0-9\-\+\#]+/}
end
Edit 1:
That is to say, for clarity's sake, when I go to mydomain.com/test/feedbacks/10 and /test2/feedbacks/10, it shows me the same view for the same record (in which case, the latter version would be wrong because it should be telling me that no such record exists, but it's not. It is just displaying the correct record for test/feedbacks/10).
Edit 2:
Here are the logs of both requests:
The right request
Started GET "/test-3/feedbacks/7" for 127.0.0.1 at 2011-09-14 02:48:15 -0500
Processing by FeedbacksController#show as HTML
Parameters: {"username"=>"test-3", "id"=>"7"}
Feedback Load (0.5ms) SELECT "feedbacks".* FROM "feedbacks" WHERE "feedbacks"."id" = ? LIMIT 1 [["id", "7"]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 LIMIT 1
Rendered feedbacks/show.html.erb within layouts/application (36.2ms)
Completed 200 OK in 188ms (Views: 184.3ms | ActiveRecord: 1.8ms)
The wrong request
Started GET "/test2/feedbacks/7" for 127.0.0.1 at 2011-09-14 02:48:28 -0500
Processing by FeedbacksController#show as HTML
Parameters: {"username"=>"test2", "id"=>"7"}
Feedback Load (0.1ms) SELECT "feedbacks".* FROM "feedbacks" WHERE "feedbacks"."id" = ? LIMIT 1 [["id", "7"]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 LIMIT 1
Rendered feedbacks/show.html.erb within layouts/application (37.6ms)
Completed 200 OK in 50ms (Views: 47.5ms | ActiveRecord: 1.2ms)
Your show action should look something like
def show
#user = User.find_by_username(params[:username])
if #user == current_user
...
render "show"
else
flash[:alert] = "Record doesn't exist"
redirect_to root_path
end
end
I took the liberty of adding in #Benoit's suggestion.