I am new to Ruby on Rails and I am creating a basic blog application.
I am getting the following error when I have confirmed that I want to delete a post/page.
ActiveRecord::RecordNotFound in
PagesController#destroy
Couldn't find Page with ID=21
{"authenticity_token"=>"JjjfnpIn4ogYhLWnbyGHjwLsy6YSgDHL+GZfOqkhSow=",
"_method"=>"delete", "id"=>"21"}
I want the user to be redirected to the listing page when they have deleted the post, I understand that it looks as though problem is with the destroy action in the controller.
My code in there is currently:
def destroy #Destroy action
#page = Page.find(params[:id])
#page.destroy
redirect_to page_url
I appreciate any advice on this.
if you're deleting a Page, you shouldn't redirect back to it because.. it won't exist
maybe try redirect_to pages_url instead of page_url
Related
I am following the tutorial from RailsGuides (Rails version is 7.0.2). Whenever I click on the destroy button, the page sends a GET request to /articles/:id, instead of the root_path that I've set to . Alternatively, I have also tried articles_path, but does not fix the issue.
This error is resolved, when I use the status: parameter, and set it to :see_other. This was not the case in older versions of Rails (v4, v6).
This does not work:
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to root_path
# [ redirect_to articles_path ] does not work as well.
end
This works:
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to root_path, status: :see_other
# [ redirect_to articles_path, status: :see_other ] will works fine too.
end
Can someone explain the reason for this behaviour?
Edit: After a little bit of research in the issues section of Rails repo, I found this Deleting article in section 6.5 of getting started guide doesn't work #43429 . From my understanding, maybe this was caused by a bug currently in Turbo-Rails ?
This is super interesting and I had to dig into the ActionController docs to find anything helpful.
In the Rails API redirect_to documentation, they state:
If you are using XHR requests other than GET or POST and redirecting after the request then some browsers will follow the redirect using the original request method. This may lead to undesirable behavior such as a double DELETE. To work around this you can return a 303 See Other status code which will be followed using a GET request.
Your controller's #destroy action should be making a DELETE request, which is included in the "other than" list mentioned in the above documentation. So it seems likely you are experiencing their example exactly! When you do not include a :status, the browser makes a double DELETE request. And since the first DELETE request deleted the record, the second DELETE request will try to delete a record that no longer exists, and return that ActiveRecord::RecordNotFound error.
When trying to redirect a POST request I'm finding that rails' flash hash is getting wiped out.
The redirect works fine when the initial request is a GET.
in config/routes.rb
post 'test/hello'
#get 'test/hello' #uncomment this line and comment out the post and the flash is preserved
get 'test/goodbye'
in app/controllers/test_controller.rb
def hello
respond_to do |format|
format.html do
redirect_to movies_goodbye_url, :notice => "I disappear on post requests"
end
end
end
def goodbye
end
in app/views/test/goodbye.html.haml
%h1 Test#goodbye
%p#alert= alert
%p#notice= notice
I want this action to handle posts from a form submission which redirects in error cases to one of my existing views. I'm pretty new to rails so if there's a better way to handle this use-case, please do let me know.
Try adding a flash.keep in there:
flash.keep(:notice)
redirect_to movies_goodbye_url, :notice => "I disappear on post requests"
See also: Flash message in redirect not working
This is probably a fairly simple thing to do - I have a site with a news feed that shows various posts. There are also other pages that similarly show posts. Comments can be added to these posts directly from any of these pages.
What I need to do is redirect the user back to the URL they came from, once they've added a comment, and to the particular post they commented on (each post has an id of post-#{post.id}, so I'd just have to stick #post-2 or whatever to the URL.
If the post could not be saved, for whatever reason, I'd also like to have the content that the user had submitted pre-filled into the comment box after the redirect.
How can I do these two things? The first is the more important one..
I'd have to store the URL that the user is coming from in the session on the new action and redirect to this on the create action? How can I get the URL?
I'm on Rails 3.1 by the way.
Thanks for the help!
You could use redirect :back which will send the user back to the page that issued the request
redirect_to :back
Assuming Comment is a resource nested under Post in your routing (/posts/123/comment/new):
def create
comment = Comment.new(params[:comment])
if comment.save
redirect_to post_path(comment.post)
else
redirect_to new_post_comment_path(params)
# or maybe you have the comment form on the Post#show page
# redirect_to post_path(params)
end
end
I'm very new to Rails, so maybe I'm just missing the "Rails way" of doing this, but I have a model, call it Post. I can create a post from the canonical posts/new page but also from another page, say home/index.
In home/index i have a form_for #post (slightly different from the one in posts/new, but say that i can use a partial). The problem is that in the PostController.create I cannot pass the newly created #post object back to home/index (in case of errors) because:
if I don't specify a page to render, it will automatically render posts/new
i don't know the calling page in order to redirect it to the right calling page (posts/new or home/index)
even if i knew it (hacking the request referrer or using redirect_to :back), redirect_to doesn't pass objects back, so that #post is empty when called from home/index
Any help? thanks
EDIT
Maybe a possible solution would be to get the calling controller / action from the request and render it back. Any way to do this?
In theory, you could achieve what you're trying to do by checking the referer:
def create
#post = Post.new
if #post.update_attributes(params[:post])
# redirect as appropriate
else
render :action => case request.referer
when new_post_path then "posts/new"
when "/" then "home/index" # assuming that home/index is the root of the site
end
end
end
To get the referrer page, you can make a hidden field with the name redirect. You can use it in the controller.
redirect_to params[:redirect] || posts_path
Have you tried that you pass the post's id in the query string to the home/index
eg: /home/index?post_id=42
You can find out who called your page by looking at
request.referrer
I don't know if this is the "rails way" but here's my solution.
You can add a route for
match home/index/(:id) => "home#index"
and redirect to this after creating the Post. Then in your Home controllers index action just do a
#Post = Post.find(params[:index]) if params[:index]
Your view should display the post if #Post exists
I like this approach because it keeps all the logic where it should be. Routing logic in the controller and view logic in the views.
I have an application where folks search for an item. If the item is found, they are presented with a list of related items found by parameters in the URL AND a contact form. I'm having issues redirecting the visitor back to the same page (with the URL parameters) after submitting the form.
Any ideas?
Try redirect_to(:back).
You could use redirect_to :back, but note that this depends on the Referer header being set, and you'll run into an error if it's not for some reason.
To get around this, I use a method like the following in my application (I put it into ApplicationController so it's accessible in all my controllers):
def redirect_back_or_to(options = {})
if request.env["HTTP_REFERER"].blank?
redirect_to options
else
redirect_to :back
end
end
Which will redirect back if the Referer header is set and otherwise work like a normal redirect_to (so you can specify where to redirect to by default).