9

I'm trying to render the integrated 404 page in rails as an exception. I tried this but still getting the routing error page:

posts_controller.rb

def destroy
if current_user.username == @post.email 
@post.destroy
respond_to do |format|
  format.html { redirect_to posts_url }
  format.json { head :no_content }
end
else
  not_found
end

application_controller.rb

 def not_found
  raise ActionController::RoutingError.new('Not Found')
end 

routes.rb

 Booklist::Application.routes.draw do
 get "pages/faq"
 get "pages/about"
 devise_for :users
 resources :posts

 root 'posts#index'
 end

view:

<% if current_user.username == post.email %>
  <font color="red">This is your post! Feel free to edit or delete it. ->  </font>
    <%= link_to 'Edit', edit_post_path(post) %>
    <%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %>
    <% end %>

No route matches [GET] "/posts/15/destroy"

franklinexpress
  • 1,149
  • 14
  • 44
  • 1
    I see the problem now `No route matches [GET] "/posts/15/destroy"`. Share the `link` code from the view which fires this action. Also, it would be handy if you share the `routes.rb` – Kirti Thorat Mar 30 '14 at 20:37
  • Did you read the above comment. – Kirti Thorat Mar 30 '14 at 20:43
  • yeah, I added routes.rb – franklinexpress Mar 30 '14 at 20:45
  • Thanks! But you forgot to add the link code from the view which fires this destroy action – Kirti Thorat Mar 30 '14 at 20:48
  • oh I see, there is no link code, I'm trying to prevent users from typing posts/postname/destroy in the url bar, that's what i'm doing and I don't want to see the error, I want to see a different page. everything works in the app each user can delete their own post only but view other user's posts with no problems – franklinexpress Mar 30 '14 at 20:50
  • @FranklinDeLosSantos may you post your link_to destroy?? Will get idea why it is giving routing error. – Alok Anand Mar 30 '14 at 20:53
  • If you are typing the url in browser's address bar as `/posts/15/destroy` then its incorrect. Because for `destroy` action the route generated should be `/posts/15` along with `DELETE` http request. If you look at yours it shows `GET` and url with `/posts/15/destroy` – Kirti Thorat Mar 30 '14 at 20:55
  • @FranklinDeLosSantos Ok got you, you have destroy link in view for post owner. And you are hiding that from other users and you are trying through urls just to get execute else part. Are you passing method as delete?? – Alok Anand Mar 30 '14 at 20:56
  • ok but how do I generate a 404 if a users types in a url incorrectly anyways? if I type http://stackoverflow.com/questions/franklin that url doesn't exist and it shows me a not found page – franklinexpress Mar 30 '14 at 20:56
  • @FranklinDeLosSantos See my UPDATE 2 in the answer. – Kirti Thorat Mar 30 '14 at 21:02

2 Answers2

15

Instead of

render not_found

you could use

render file: "#{Rails.root}/public/404.html" , status: 404

Or

render file: "#{Rails.root}/public/404.html" , status: :not_found

UPDATE

def destroy
  if current_user.username == @post.email 
    @post.destroy
    respond_to do |format|
      format.html { redirect_to posts_url }
      format.json { head :no_content }
    end
  else
    render file: "#{Rails.root}/public/404.html" , status: :not_found
  end
end  ## end is missing

UPDATE 2

If you want to display 404 error page in development environment then make sure that the following is set to false in development.rb file:

  config.consider_all_requests_local       = false 

WARNING: This also means that you would not see any errors raised on your application(stacktrace etc in view).

Kirti Thorat
  • 52,578
  • 9
  • 101
  • 108
  • tried this, same error, it looks like my else statement isn't executed, I did a `puts "test"` to see if i'd see anything in the console but nada – franklinexpress Mar 30 '14 at 20:23
  • That means `current_user.username == @post.email ` is aalways true. Else would only be executed if above condition is false. – Kirti Thorat Mar 30 '14 at 20:27
  • that's weird because I have a page listing the current user's posts only and there it shows the destroy and edit links but it doesn't show the links to posts not belonging to that user and I'm using `if current_user.username == @post.email ` as well and it works fine – franklinexpress Mar 30 '14 at 20:30
  • @FranklinDeLosSantos See my UPDATE above. I found one missing `end`. Maybe it was a typo but just wanted to be sure. – Kirti Thorat Mar 30 '14 at 20:30
  • yeah that's a typo, the app wouldn't run if it was a missing end thankfully :) – franklinexpress Mar 30 '14 at 20:32
  • @FranklinDeLosSantos Also, how do you set @post? Do you have a before_action for `destroy`? – Kirti Thorat Mar 30 '14 at 20:33
  • @FranklinDeLosSantos You could `puts` the values of `current_user.username and @post.email ` before the `if statement` in `destroy` action. See what it shows. – Kirti Thorat Mar 30 '14 at 20:34
  • @FranklinDeLosSantos Finally.. Time for coffee. – Kirti Thorat Mar 30 '14 at 21:11
  • @KirtiThorat +1 for warning :), but how did you understand Santos's quest? I was thinking, as he was telling it, he wants to know the reason behind 'else' part not getting executed. – Alok Anand Mar 30 '14 at 21:19
  • @KirtiThorat Happy Gudi Padwa to you. – Alok Anand Mar 30 '14 at 21:21
  • 1
    @AlokAnand Happy Gudi Padwa to you too. :) How did I know? OP's comment `but how do I generate a 404 if a users types in a url incorrectly anyways?` – Kirti Thorat Mar 30 '14 at 21:26
1

You need to place not_found in ApplicationController, not in PostsController, and then you don't need to render it, you can just call it like

# your code above...
else
  not_found
end
Robert Krzyzanowski
  • 9,294
  • 28
  • 24