From fe4e15b515198cb2f3ae169f2157ce2552a40843 Mon Sep 17 00:00:00 2001 From: Matthew Bender Date: Sat, 22 Nov 2014 15:58:18 -0700 Subject: [PATCH] display 404 page: invalid route / record not found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - rescue_from ActionController::RoutingError doesn’t do anything - `unless Rails.env.production?` made record not found work - added tests! :-) - new errors controller - handle 422 & 500 errors with public pages - annotate routes --- app/controllers/application_controller.rb | 5 +- app/controllers/errors_controller.rb | 21 + app/views/error/not_found.json | 1 - app/views/error/not_found.xml | 1 - .../_helpful_links.html.haml | 0 .../{error => errors}/not_found.html.haml | 3 +- app/views/errors/not_found.json | 1 + app/views/errors/not_found.xml | 1 + config/application.rb | 2 + config/routes.rb | 536 +++++++++--------- spec/features/errors/internal_error_spec.rb | 22 + spec/features/errors/not_found_spec.rb | 25 + 12 files changed, 345 insertions(+), 273 deletions(-) create mode 100644 app/controllers/errors_controller.rb delete mode 100644 app/views/error/not_found.json delete mode 100644 app/views/error/not_found.xml rename app/views/{error => errors}/_helpful_links.html.haml (100%) rename app/views/{error => errors}/not_found.html.haml (91%) create mode 100644 app/views/errors/not_found.json create mode 100644 app/views/errors/not_found.xml create mode 100644 spec/features/errors/internal_error_spec.rb create mode 100644 spec/features/errors/not_found_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3afefbe0..9415dd39 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -21,8 +21,7 @@ class ApplicationController < ActionController::Base after_action :record_visit after_action :record_location - rescue_from ActiveRecord::RecordNotFound, with: :render_404 unless Rails.env.production? - rescue_from ActionController::RoutingError, with: :render_404 unless Rails.env.production? + rescue_from ActiveRecord::RecordNotFound, with: :render_404 protected @@ -183,7 +182,7 @@ def not_on_achievements? end def render_404 - render template: 'error/not_found', status: :not_found + render template: 'errors/not_found', status: :not_found end def render_500 diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb new file mode 100644 index 00000000..70909fb0 --- /dev/null +++ b/app/controllers/errors_controller.rb @@ -0,0 +1,21 @@ +class ErrorsController < ApplicationController + def not_found + render status: :not_found + end + + def unacceptable + respond_to do |format| + format.html { render 'public/422', status: :unprocessable_entity } + format.xml { head :unprocessable_entity } + format.json { head :unprocessable_entity } + end + end + + def internal_error + respond_to do |format| + format.html { render 'public/500', status: :internal_server_error } + format.xml { head :internal_server_error } + format.json { head :internal_server_error } + end + end +end diff --git a/app/views/error/not_found.json b/app/views/error/not_found.json deleted file mode 100644 index 9e26dfee..00000000 --- a/app/views/error/not_found.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/app/views/error/not_found.xml b/app/views/error/not_found.xml deleted file mode 100644 index f3316a03..00000000 --- a/app/views/error/not_found.xml +++ /dev/null @@ -1 +0,0 @@ -404 \ No newline at end of file diff --git a/app/views/error/_helpful_links.html.haml b/app/views/errors/_helpful_links.html.haml similarity index 100% rename from app/views/error/_helpful_links.html.haml rename to app/views/errors/_helpful_links.html.haml diff --git a/app/views/error/not_found.html.haml b/app/views/errors/not_found.html.haml similarity index 91% rename from app/views/error/not_found.html.haml rename to app/views/errors/not_found.html.haml index 4bc89a11..48329300 100644 --- a/app/views/error/not_found.html.haml +++ b/app/views/errors/not_found.html.haml @@ -9,5 +9,4 @@ If you don't believe you should be seeing this error, #{ link_to "please contact us", contact_us_path }! - = render partial: "error/helpful_links" - + = render partial: "errors/helpful_links" diff --git a/app/views/errors/not_found.json b/app/views/errors/not_found.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/app/views/errors/not_found.json @@ -0,0 +1 @@ +{} diff --git a/app/views/errors/not_found.xml b/app/views/errors/not_found.xml new file mode 100644 index 00000000..d97b09fe --- /dev/null +++ b/app/views/errors/not_found.xml @@ -0,0 +1 @@ +404 diff --git a/config/application.rb b/config/application.rb index 014b0d16..dc5ec915 100644 --- a/config/application.rb +++ b/config/application.rb @@ -39,6 +39,8 @@ class Application < Rails::Application config.rakismet.key = ENV['AKISMET_KEY'] config.rakismet.url = ENV['AKISMET_URL'] + + config.exceptions_app = self.routes end end diff --git a/config/routes.rb b/config/routes.rb index c9c892da..a25105f7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,270 +1,271 @@ # == Route Map # -# Connecting to database specified by database.yml -# Creating scope :featured. Overwriting existing method Team.featured. -# GET /.json(.:format) # -# GET /teams/.json(.:format) # -# /mail_view MailPreview -# protips_update GET|PUT /protips/update(.:format) protips#update -# protip_update GET|PUT /protip/update(.:format) protip#update -# welcome GET /welcome(.:format) home#index -# root / protips#index -# p_dpvbbg GET /p/dpvbbg(.:format) protips#show {:id=>"devsal"} -# gh GET /gh(.:format) protips#show {:utm_campaign=>"github_orgs_badges", :utm_source=>"github"} -# jobs GET /jobs(/:location(/:skill))(.:format) opportunities#index -# jobs_map GET /jobs-map(.:format) opportunities#map -# slug_protips GET /p/:id/:slug(.:format) protips#show {:slug=>/(?!.*?edit).*/} -# random_protips GET /p/random(.:format) protips#random -# search_protips GET /p/search(.:format) protips#search -# POST /p/search(.:format) protips#search -# my_protips GET /p/me(.:format) protips#me -# reviewable_protips GET /p/admin(.:format) protips#admin -# team_protips GET /p/team/:team_slug(.:format) protips#team -# date_protips GET /p/d/:date(/:start)(.:format) protips#date -# trending_topics_protips GET /p/t/trending(.:format) protips#trending -# by_tags_protips GET /p/t/by_tags(.:format) protips#by_tags -# user_protips GET /p/u/:username(.:format) protips#user -# tagged_protips GET /p/t(/*tags)(.:format) networks#tag -# subscribe_protips PUT /p/t(/*tags)/subscribe(.:format) protips#subscribe -# unsubscribe_protips PUT /p/t(/*tags)/unsubscribe(.:format) protips#unsubscribe -# fresh_protips GET /p/fresh(.:format) protips#fresh -# trending_protips GET /p/trending(.:format) protips#trending -# popular_protips GET /p/popular(.:format) protips#popular -# liked_protips GET /p/liked(.:format) protips#liked -# preview_protips POST /p/preview(.:format) protips#preview -# upvote_protip POST /p/:id/upvote(.:format) protips#upvote -# report_inappropriate_protip POST /p/:id/report_inappropriate(.:format) protips#report_inappropriate -# tag_protip POST /p/:id/tag(.:format) protips#tag -# flag_protip POST /p/:id/flag(.:format) protips#flag -# feature_protip POST /p/:id/feature(.:format) protips#feature -# delete_tag_protip POST /p/:id/delete_tag/:topic(.:format) protips#delete_tag {:topic=>/[A-Za-z0-9#\$\+\-_\.(%23)(%24)(%2B)]+/} -# like_protip_comment POST /p/:protip_id/comments/:id/like(.:format) comments#like {:id=>/\d+/} -# protip_comments GET /p/:protip_id/comments(.:format) comments#index {:id=>/\d+/} -# POST /p/:protip_id/comments(.:format) comments#create {:id=>/\d+/} -# new_protip_comment GET /p/:protip_id/comments/new(.:format) comments#new {:id=>/\d+/} -# edit_protip_comment GET /p/:protip_id/comments/:id/edit(.:format) comments#edit {:id=>/\d+/} -# protip_comment GET /p/:protip_id/comments/:id(.:format) comments#show {:id=>/\d+/} -# PUT /p/:protip_id/comments/:id(.:format) comments#update {:id=>/\d+/} -# DELETE /p/:protip_id/comments/:id(.:format) comments#destroy {:id=>/\d+/} -# protips GET /p(.:format) protips#index -# POST /p(.:format) protips#create -# new_protip GET /p/new(.:format) protips#new -# edit_protip GET /p/:id/edit(.:format) protips#edit -# protip GET /p/:id(.:format) protips#show -# PUT /p/:id(.:format) protips#update -# DELETE /p/:id(.:format) protips#destroy -# featured_networks GET /n/featured(.:format) networks#featured {:slug=>/[\dA-Z\-]/i} -# user_networks GET /n/u/:username(.:format) networks#user {:slug=>/[\dA-Z\-]/i} -# tagged_network GET /n/:id/t(/*tags)(.:format) networks#tag {:slug=>/[\dA-Z\-]/i} -# members_network GET /n/:id/members(.:format) networks#members {:slug=>/[\dA-Z\-]/i} -# mayor_network GET /n/:id/mayor(.:format) networks#mayor {:slug=>/[\dA-Z\-]/i} -# expert_network GET /n/:id/expert(.:format) networks#expert {:slug=>/[\dA-Z\-]/i} -# join_network POST /n/:id/join(.:format) networks#join {:slug=>/[\dA-Z\-]/i} -# leave_network POST /n/:id/leave(.:format) networks#leave {:slug=>/[\dA-Z\-]/i} -# update_tags_network POST /n/:id/update-tags(.:format) networks#update_tags {:slug=>/[\dA-Z\-]/i} -# current_mayor_network GET /n/:id/current-mayor(.:format) networks#current_mayor {:slug=>/[\dA-Z\-]/i} -# networks GET /n(.:format) networks#index {:slug=>/[\dA-Z\-]/i} -# POST /n(.:format) networks#create {:slug=>/[\dA-Z\-]/i} -# new_network GET /n/new(.:format) networks#new {:slug=>/[\dA-Z\-]/i} -# edit_network GET /n/:id/edit(.:format) networks#edit {:slug=>/[\dA-Z\-]/i} -# network GET /n/:id(.:format) networks#show {:slug=>/[\dA-Z\-]/i} -# PUT /n/:id(.:format) networks#update {:slug=>/[\dA-Z\-]/i} -# DELETE /n/:id(.:format) networks#destroy {:slug=>/[\dA-Z\-]/i} -# protips GET /trending(.:format) protips#index -# faq GET /faq(.:format) pages#show {:page=>:faq} -# tos GET /tos(.:format) pages#show {:page=>:tos} -# privacy_policy GET /privacy_policy(.:format) pages#show {:page=>:privacy_policy} -# contact_us GET /contact_us(.:format) pages#show {:page=>:contact_us} -# api GET /api(.:format) pages#show {:page=>:api} -# achievements GET /achievements(.:format) pages#show {:page=>:achievements} -# GET /pages/:page(.:format) pages#show -# award_badge GET /award(.:format) achievements#award -# authenticate GET|POST /auth/:provider/callback(.:format) sessions#create -# authentication_failure GET /auth/failure(.:format) sessions#failure -# settings GET /settings(.:format) users#edit -# GET /redeem/:code(.:format) redemptions#show -# unsubscribe GET /unsubscribe(.:format) emails#unsubscribe -# delivered GET /delivered(.:format) emails#delivered -# delete_account GET /delete_account(.:format) users#delete_account -# delete_account_confirmed POST /delete_account_confirmed(.:format) users#delete_account_confirmed -# authentications GET /authentications(.:format) authentications#index -# POST /authentications(.:format) authentications#create -# new_authentication GET /authentications/new(.:format) authentications#new -# edit_authentication GET /authentications/:id/edit(.:format) authentications#edit -# authentication GET /authentications/:id(.:format) authentications#show -# PUT /authentications/:id(.:format) authentications#update -# DELETE /authentications/:id(.:format) authentications#destroy -# usernames GET /usernames(.:format) usernames#index -# POST /usernames(.:format) usernames#create -# new_username GET /usernames/new(.:format) usernames#new -# edit_username GET /usernames/:id/edit(.:format) usernames#edit -# username GET /usernames/:id(.:format) usernames#show -# PUT /usernames/:id(.:format) usernames#update -# DELETE /usernames/:id(.:format) usernames#destroy -# invitations GET /invitations(.:format) invitations#index -# POST /invitations(.:format) invitations#create -# new_invitation GET /invitations/new(.:format) invitations#new -# edit_invitation GET /invitations/:id/edit(.:format) invitations#edit -# invitation GET /invitations/:id(.:format) invitations#show -# PUT /invitations/:id(.:format) invitations#update -# DELETE /invitations/:id(.:format) invitations#destroy -# invitation GET /i/:id/:r(.:format) invitations#show -# force_sessions GET /sessions/force(.:format) sessions#force -# sessions GET /sessions(.:format) sessions#index -# POST /sessions(.:format) sessions#create -# new_session GET /sessions/new(.:format) sessions#new -# edit_session GET /sessions/:id/edit(.:format) sessions#edit -# session GET /sessions/:id(.:format) sessions#show -# PUT /sessions/:id(.:format) sessions#update -# DELETE /sessions/:id(.:format) sessions#destroy -# webhooks_stripe GET /webhooks/stripe(.:format) accounts#webhook -# alerts GET /alerts(.:format) alerts#create -# GET /alerts(.:format) alerts#index -# follow_user POST /users/:username/follow(.:format) follows#create {:type=>:user} -# teamname GET /team/:slug(.:format) teams#show -# teamname_edit GET /team/:slug/edit(.:format) teams#edit -# job GET /team/:slug(/:job_id)(.:format) teams#show -# accept_team GET /teams/:id/accept(.:format) teams#accept -# record_exit_team POST /teams/:id/record-exit(.:format) teams#record_exit -# visitors_team GET /teams/:id/visitors(.:format) teams#visitors -# follow_team POST /teams/:id/follow(.:format) teams#follow -# join_team POST /teams/:id/join(.:format) teams#join -# approve_join_team POST /teams/:id/join/:user_id/approve(.:format) teams#approve_join -# deny_join_team POST /teams/:id/join/:user_id/deny(.:format) teams#deny_join -# inquiry_teams POST /teams/inquiry(.:format) teams#inquiry -# followed_teams GET /teams/followed(.:format) teams#followed -# search_teams GET /teams/search(.:format) teams#search -# team_members GET /teams/:team_id/members(.:format) members#index -# POST /teams/:team_id/members(.:format) members#create -# new_team_member GET /teams/:team_id/members/new(.:format) members#new -# edit_team_member GET /teams/:team_id/members/:id/edit(.:format) members#edit -# team_member GET /teams/:team_id/members/:id(.:format) members#show -# PUT /teams/:team_id/members/:id(.:format) members#update -# DELETE /teams/:team_id/members/:id(.:format) members#destroy -# team_locations GET /teams/:team_id/locations(.:format) locations#index -# POST /teams/:team_id/locations(.:format) locations#create -# new_team_location GET /teams/:team_id/locations/new(.:format) locations#new -# edit_team_location GET /teams/:team_id/locations/:id/edit(.:format) locations#edit -# team_location GET /teams/:team_id/locations/:id(.:format) locations#show -# PUT /teams/:team_id/locations/:id(.:format) locations#update -# DELETE /teams/:team_id/locations/:id(.:format) locations#destroy -# apply_team_opportunity POST /teams/:team_id/opportunities/:id/apply(.:format) opportunities#apply -# activate_team_opportunity GET /teams/:team_id/opportunities/:id/activate(.:format) opportunities#activate -# deactivate_team_opportunity GET /teams/:team_id/opportunities/:id/deactivate(.:format) opportunities#deactivate -# visit_team_opportunity POST /teams/:team_id/opportunities/:id/visit(.:format) opportunities#visit -# team_opportunities GET /teams/:team_id/opportunities(.:format) opportunities#index -# POST /teams/:team_id/opportunities(.:format) opportunities#create -# new_team_opportunity GET /teams/:team_id/opportunities/new(.:format) opportunities#new -# edit_team_opportunity GET /teams/:team_id/opportunities/:id/edit(.:format) opportunities#edit -# team_opportunity GET /teams/:team_id/opportunities/:id(.:format) opportunities#show -# PUT /teams/:team_id/opportunities/:id(.:format) opportunities#update -# DELETE /teams/:team_id/opportunities/:id(.:format) opportunities#destroy -# send_invoice_team_account POST /teams/:team_id/account/send_invoice(.:format) accounts#send_invoice -# team_account POST /teams/:team_id/account(.:format) accounts#create -# new_team_account GET /teams/:team_id/account/new(.:format) accounts#new -# edit_team_account GET /teams/:team_id/account/edit(.:format) accounts#edit -# GET /teams/:team_id/account(.:format) accounts#show -# PUT /teams/:team_id/account(.:format) accounts#update -# DELETE /teams/:team_id/account(.:format) accounts#destroy -# teams GET /teams(.:format) teams#index -# POST /teams(.:format) teams#create -# new_team GET /teams/new(.:format) teams#new -# edit_team GET /teams/:id/edit(.:format) teams#edit -# team GET /teams/:id(.:format) teams#show -# PUT /teams/:id(.:format) teams#update -# DELETE /teams/:id(.:format) teams#destroy -# leaderboard GET /leaderboard(.:format) teams#leaderboard -# employers GET /employers(.:format) teams#upgrade -# unlink_github POST /github/unlink(.:format) users#unlink_provider {:provider=>"github"} -# GET /github/:username(.:format) users#show {:provider=>"github"} -# unlink_twitter POST /twitter/unlink(.:format) users#unlink_provider {:provider=>"twitter"} -# GET /twitter/:username(.:format) users#show {:provider=>"twitter"} -# unlink_forrst POST /forrst/unlink(.:format) users#unlink_provider {:provider=>"forrst"} -# GET /forrst/:username(.:format) users#show {:provider=>"forrst"} -# unlink_dribbble POST /dribbble/unlink(.:format) users#unlink_provider {:provider=>"dribbble"} -# GET /dribbble/:username(.:format) users#show {:provider=>"dribbble"} -# unlink_linkedin POST /linkedin/unlink(.:format) users#unlink_provider {:provider=>"linkedin"} -# GET /linkedin/:username(.:format) users#show {:provider=>"linkedin"} -# unlink_codeplex POST /codeplex/unlink(.:format) users#unlink_provider {:provider=>"codeplex"} -# GET /codeplex/:username(.:format) users#show {:provider=>"codeplex"} -# unlink_bitbucket POST /bitbucket/unlink(.:format) users#unlink_provider {:provider=>"bitbucket"} -# GET /bitbucket/:username(.:format) users#show {:provider=>"bitbucket"} -# unlink_stackoverflow POST /stackoverflow/unlink(.:format) users#unlink_provider {:provider=>"stackoverflow"} -# GET /stackoverflow/:username(.:format) users#show {:provider=>"stackoverflow"} -# resume_uploads POST /resume_uploads(.:format) resume_uploads#create -# invite_users POST /users/invite(.:format) users#invite -# autocomplete_users GET /users/autocomplete(.:format) users#autocomplete -# status_users GET /users/status(.:format) users#status -# specialties_user POST /users/:id/specialties(.:format) users#specialties -# user_skills GET /users/:user_id/skills(.:format) skills#index -# POST /users/:user_id/skills(.:format) skills#create -# new_user_skill GET /users/:user_id/skills/new(.:format) skills#new -# edit_user_skill GET /users/:user_id/skills/:id/edit(.:format) skills#edit -# user_skill GET /users/:user_id/skills/:id(.:format) skills#show -# PUT /users/:user_id/skills/:id(.:format) skills#update -# DELETE /users/:user_id/skills/:id(.:format) skills#destroy -# user_highlights GET /users/:user_id/highlights(.:format) highlights#index -# POST /users/:user_id/highlights(.:format) highlights#create -# new_user_highlight GET /users/:user_id/highlights/new(.:format) highlights#new -# edit_user_highlight GET /users/:user_id/highlights/:id/edit(.:format) highlights#edit -# user_highlight GET /users/:user_id/highlights/:id(.:format) highlights#show -# PUT /users/:user_id/highlights/:id(.:format) highlights#update -# DELETE /users/:user_id/highlights/:id(.:format) highlights#destroy -# user_endorsements GET /users/:user_id/endorsements(.:format) endorsements#index -# POST /users/:user_id/endorsements(.:format) endorsements#create -# new_user_endorsement GET /users/:user_id/endorsements/new(.:format) endorsements#new -# edit_user_endorsement GET /users/:user_id/endorsements/:id/edit(.:format) endorsements#edit -# user_endorsement GET /users/:user_id/endorsements/:id(.:format) endorsements#show -# PUT /users/:user_id/endorsements/:id(.:format) endorsements#update -# DELETE /users/:user_id/endorsements/:id(.:format) endorsements#destroy -# user_pictures GET /users/:user_id/pictures(.:format) pictures#index -# POST /users/:user_id/pictures(.:format) pictures#create -# new_user_picture GET /users/:user_id/pictures/new(.:format) pictures#new -# edit_user_picture GET /users/:user_id/pictures/:id/edit(.:format) pictures#edit -# user_picture GET /users/:user_id/pictures/:id(.:format) pictures#show -# PUT /users/:user_id/pictures/:id(.:format) pictures#update -# DELETE /users/:user_id/pictures/:id(.:format) pictures#destroy -# user_follows GET /users/:user_id/follows(.:format) follows#index -# POST /users/:user_id/follows(.:format) follows#create -# new_user_follow GET /users/:user_id/follows/new(.:format) follows#new -# edit_user_follow GET /users/:user_id/follows/:id/edit(.:format) follows#edit -# user_follow GET /users/:user_id/follows/:id(.:format) follows#show -# PUT /users/:user_id/follows/:id(.:format) follows#update -# DELETE /users/:user_id/follows/:id(.:format) follows#destroy -# user_bans POST /users/:user_id/bans(.:format) bans#create -# user_unbans POST /users/:user_id/unbans(.:format) unbans#create -# users GET /users(.:format) users#index -# POST /users(.:format) users#create -# new_user GET /users/new(.:format) users#new -# edit_user GET /users/:id/edit(.:format) users#edit -# user GET /users/:id(.:format) users#show -# PUT /users/:id(.:format) users#update -# DELETE /users/:id(.:format) users#destroy -# clear_provider GET /clear/:id/:provider(.:format) users#clear_provider -# refresh GET /refresh/:username(.:format) users#refresh -# random_accomplishment GET /nextaccomplishment(.:format) highlights#random -# add_skill GET /add-skill(.:format) skills#create -# blog GET /blog(.:format) blog_posts#index -# blog_post GET /blog/:id(.:format) blog_posts#show -# atom GET /articles.atom(.:format) blog_posts#index {:format=>:atom} -# signin GET /signin(.:format) sessions#signin -# signout GET /signout(.:format) sessions#destroy -# sign_out GET /goodbye(.:format) sessions#destroy -# random_wall GET /roll-the-dice(.:format) users#randomize -# GET /providers/:provider/:username(.:format) provider_user_lookups#show -# badge GET /:username(.:format) users#show -# user_achievement GET /:username/achievements/:id(.:format) achievements#show -# GET /:username/endorsements.json(.:format) endorsements#show -# followers GET /:username/followers(.:format) follows#index {:type=>:followers} -# following GET /:username/following(.:format) follows#index {:type=>:following} -# callbacks_hawt_feature POST /callbacks/hawt/feature(.:format) callbacks/hawt#feature -# callbacks_hawt_unfeature POST /callbacks/hawt/unfeature(.:format) callbacks/hawt#unfeature -# admin_root GET /admin(.:format) admin#index -# admin_teams GET /admin/teams(.:format) admin#teams -# admin_sections_teams GET /admin/teams/sections/:num_sections(.:format) admin#sections_teams -# admin_section_teams GET /admin/teams/section/:section(.:format) admin#section_teams -# admin_sidekiq_web /admin/sidekiq Sidekiq::Web -# latest_comments GET /comments(.:format) comments#index +# GET /.json(.:format) # +# GET /teams/.json(.:format) # +# /mail_view MailPreview +# protips_update GET|PUT /protips/update(.:format) protips#update +# protip_update GET|PUT /protip/update(.:format) protip#update +# welcome GET /welcome(.:format) home#index +# root / protips#index +# p_dpvbbg GET /p/dpvbbg(.:format) protips#show {:id=>"devsal"} +# gh GET /gh(.:format) protips#show {:utm_campaign=>"github_orgs_badges", :utm_source=>"github"} +# jobs GET /jobs(/:location(/:skill))(.:format) opportunities#index +# jobs_map GET /jobs-map(.:format) opportunities#map +# slug_protips GET /p/:id/:slug(.:format) protips#show {:slug=>/(?!.*?edit).*/} +# random_protips GET /p/random(.:format) protips#random +# search_protips GET /p/search(.:format) protips#search +# POST /p/search(.:format) protips#search +# my_protips GET /p/me(.:format) protips#me +# reviewable_protips GET /p/admin(.:format) protips#admin +# team_protips GET /p/team/:team_slug(.:format) protips#team +# date_protips GET /p/d/:date(/:start)(.:format) protips#date +# trending_topics_protips GET /p/t/trending(.:format) protips#trending +# by_tags_protips GET /p/t/by_tags(.:format) protips#by_tags +# user_protips GET /p/u/:username(.:format) protips#user +# tagged_protips GET /p/t(/*tags)(.:format) networks#tag +# subscribe_protips PUT /p/t(/*tags)/subscribe(.:format) protips#subscribe +# unsubscribe_protips PUT /p/t(/*tags)/unsubscribe(.:format) protips#unsubscribe +# fresh_protips GET /p/fresh(.:format) protips#fresh +# trending_protips GET /p/trending(.:format) protips#trending +# popular_protips GET /p/popular(.:format) protips#popular +# liked_protips GET /p/liked(.:format) protips#liked +# preview_protips POST /p/preview(.:format) protips#preview +# upvote_protip POST /p/:id/upvote(.:format) protips#upvote +# report_inappropriate_protip POST /p/:id/report_inappropriate(.:format) protips#report_inappropriate +# tag_protip POST /p/:id/tag(.:format) protips#tag +# flag_protip POST /p/:id/flag(.:format) protips#flag +# feature_protip POST /p/:id/feature(.:format) protips#feature +# delete_tag_protip POST /p/:id/delete_tag/:topic(.:format) protips#delete_tag {:topic=>/[A-Za-z0-9#\$\+\-_\.(%23)(%24)(%2B)]+/} +# like_protip_comment POST /p/:protip_id/comments/:id/like(.:format) comments#like {:id=>/\d+/} +# protip_comments GET /p/:protip_id/comments(.:format) comments#index {:id=>/\d+/} +# POST /p/:protip_id/comments(.:format) comments#create {:id=>/\d+/} +# new_protip_comment GET /p/:protip_id/comments/new(.:format) comments#new {:id=>/\d+/} +# edit_protip_comment GET /p/:protip_id/comments/:id/edit(.:format) comments#edit {:id=>/\d+/} +# protip_comment GET /p/:protip_id/comments/:id(.:format) comments#show {:id=>/\d+/} +# PUT /p/:protip_id/comments/:id(.:format) comments#update {:id=>/\d+/} +# DELETE /p/:protip_id/comments/:id(.:format) comments#destroy {:id=>/\d+/} +# protips GET /p(.:format) protips#index +# POST /p(.:format) protips#create +# new_protip GET /p/new(.:format) protips#new +# edit_protip GET /p/:id/edit(.:format) protips#edit +# protip GET /p/:id(.:format) protips#show +# PUT /p/:id(.:format) protips#update +# DELETE /p/:id(.:format) protips#destroy +# featured_networks GET /n/featured(.:format) networks#featured {:slug=>/[\dA-Z\-]/i} +# user_networks GET /n/u/:username(.:format) networks#user {:slug=>/[\dA-Z\-]/i} +# tagged_network GET /n/:id/t(/*tags)(.:format) networks#tag {:slug=>/[\dA-Z\-]/i} +# members_network GET /n/:id/members(.:format) networks#members {:slug=>/[\dA-Z\-]/i} +# mayor_network GET /n/:id/mayor(.:format) networks#mayor {:slug=>/[\dA-Z\-]/i} +# expert_network GET /n/:id/expert(.:format) networks#expert {:slug=>/[\dA-Z\-]/i} +# join_network POST /n/:id/join(.:format) networks#join {:slug=>/[\dA-Z\-]/i} +# leave_network POST /n/:id/leave(.:format) networks#leave {:slug=>/[\dA-Z\-]/i} +# update_tags_network POST /n/:id/update-tags(.:format) networks#update_tags {:slug=>/[\dA-Z\-]/i} +# current_mayor_network GET /n/:id/current-mayor(.:format) networks#current_mayor {:slug=>/[\dA-Z\-]/i} +# networks GET /n(.:format) networks#index {:slug=>/[\dA-Z\-]/i} +# POST /n(.:format) networks#create {:slug=>/[\dA-Z\-]/i} +# new_network GET /n/new(.:format) networks#new {:slug=>/[\dA-Z\-]/i} +# edit_network GET /n/:id/edit(.:format) networks#edit {:slug=>/[\dA-Z\-]/i} +# network GET /n/:id(.:format) networks#show {:slug=>/[\dA-Z\-]/i} +# PUT /n/:id(.:format) networks#update {:slug=>/[\dA-Z\-]/i} +# DELETE /n/:id(.:format) networks#destroy {:slug=>/[\dA-Z\-]/i} +# protips GET /trending(.:format) protips#index +# faq GET /faq(.:format) pages#show {:page=>:faq} +# tos GET /tos(.:format) pages#show {:page=>:tos} +# privacy_policy GET /privacy_policy(.:format) pages#show {:page=>:privacy_policy} +# contact_us GET /contact_us(.:format) pages#show {:page=>:contact_us} +# api GET /api(.:format) pages#show {:page=>:api} +# achievements GET /achievements(.:format) pages#show {:page=>:achievements} +# GET /pages/:page(.:format) pages#show +# award_badge GET /award(.:format) achievements#award +# authenticate GET|POST /auth/:provider/callback(.:format) sessions#create +# authentication_failure GET /auth/failure(.:format) sessions#failure +# settings GET /settings(.:format) users#edit +# GET /redeem/:code(.:format) redemptions#show +# unsubscribe GET /unsubscribe(.:format) emails#unsubscribe +# delivered GET /delivered(.:format) emails#delivered +# delete_account GET /delete_account(.:format) users#delete_account +# delete_account_confirmed POST /delete_account_confirmed(.:format) users#delete_account_confirmed +# authentications GET /authentications(.:format) authentications#index +# POST /authentications(.:format) authentications#create +# new_authentication GET /authentications/new(.:format) authentications#new +# edit_authentication GET /authentications/:id/edit(.:format) authentications#edit +# authentication GET /authentications/:id(.:format) authentications#show +# PUT /authentications/:id(.:format) authentications#update +# DELETE /authentications/:id(.:format) authentications#destroy +# usernames GET /usernames(.:format) usernames#index +# POST /usernames(.:format) usernames#create +# new_username GET /usernames/new(.:format) usernames#new +# edit_username GET /usernames/:id/edit(.:format) usernames#edit +# username GET /usernames/:id(.:format) usernames#show +# PUT /usernames/:id(.:format) usernames#update +# DELETE /usernames/:id(.:format) usernames#destroy +# invitations GET /invitations(.:format) invitations#index +# POST /invitations(.:format) invitations#create +# new_invitation GET /invitations/new(.:format) invitations#new +# edit_invitation GET /invitations/:id/edit(.:format) invitations#edit +# invitation GET /invitations/:id(.:format) invitations#show +# PUT /invitations/:id(.:format) invitations#update +# DELETE /invitations/:id(.:format) invitations#destroy +# invitation GET /i/:id/:r(.:format) invitations#show +# force_sessions GET /sessions/force(.:format) sessions#force +# sessions GET /sessions(.:format) sessions#index +# POST /sessions(.:format) sessions#create +# new_session GET /sessions/new(.:format) sessions#new +# edit_session GET /sessions/:id/edit(.:format) sessions#edit +# session GET /sessions/:id(.:format) sessions#show +# PUT /sessions/:id(.:format) sessions#update +# DELETE /sessions/:id(.:format) sessions#destroy +# webhooks_stripe GET /webhooks/stripe(.:format) accounts#webhook +# alerts GET /alerts(.:format) alerts#create +# GET /alerts(.:format) alerts#index +# follow_user POST /users/:username/follow(.:format) follows#create {:type=>:user} +# teamname GET /team/:slug(.:format) teams#show +# teamname_edit GET /team/:slug/edit(.:format) teams#edit +# job GET /team/:slug(/:job_id)(.:format) teams#show +# accept_team GET /teams/:id/accept(.:format) teams#accept +# record_exit_team POST /teams/:id/record-exit(.:format) teams#record_exit +# visitors_team GET /teams/:id/visitors(.:format) teams#visitors +# follow_team POST /teams/:id/follow(.:format) teams#follow +# join_team POST /teams/:id/join(.:format) teams#join +# approve_join_team POST /teams/:id/join/:user_id/approve(.:format) teams#approve_join +# deny_join_team POST /teams/:id/join/:user_id/deny(.:format) teams#deny_join +# inquiry_teams POST /teams/inquiry(.:format) teams#inquiry +# followed_teams GET /teams/followed(.:format) teams#followed +# search_teams GET /teams/search(.:format) teams#search +# team_members GET /teams/:team_id/members(.:format) members#index +# POST /teams/:team_id/members(.:format) members#create +# new_team_member GET /teams/:team_id/members/new(.:format) members#new +# edit_team_member GET /teams/:team_id/members/:id/edit(.:format) members#edit +# team_member GET /teams/:team_id/members/:id(.:format) members#show +# PUT /teams/:team_id/members/:id(.:format) members#update +# DELETE /teams/:team_id/members/:id(.:format) members#destroy +# team_locations GET /teams/:team_id/locations(.:format) locations#index +# POST /teams/:team_id/locations(.:format) locations#create +# new_team_location GET /teams/:team_id/locations/new(.:format) locations#new +# edit_team_location GET /teams/:team_id/locations/:id/edit(.:format) locations#edit +# team_location GET /teams/:team_id/locations/:id(.:format) locations#show +# PUT /teams/:team_id/locations/:id(.:format) locations#update +# DELETE /teams/:team_id/locations/:id(.:format) locations#destroy +# apply_team_opportunity POST /teams/:team_id/opportunities/:id/apply(.:format) opportunities#apply +# activate_team_opportunity GET /teams/:team_id/opportunities/:id/activate(.:format) opportunities#activate +# deactivate_team_opportunity GET /teams/:team_id/opportunities/:id/deactivate(.:format) opportunities#deactivate +# visit_team_opportunity POST /teams/:team_id/opportunities/:id/visit(.:format) opportunities#visit +# team_opportunities GET /teams/:team_id/opportunities(.:format) opportunities#index +# POST /teams/:team_id/opportunities(.:format) opportunities#create +# new_team_opportunity GET /teams/:team_id/opportunities/new(.:format) opportunities#new +# edit_team_opportunity GET /teams/:team_id/opportunities/:id/edit(.:format) opportunities#edit +# team_opportunity GET /teams/:team_id/opportunities/:id(.:format) opportunities#show +# PUT /teams/:team_id/opportunities/:id(.:format) opportunities#update +# DELETE /teams/:team_id/opportunities/:id(.:format) opportunities#destroy +# send_invoice_team_account POST /teams/:team_id/account/send_invoice(.:format) accounts#send_invoice +# team_account POST /teams/:team_id/account(.:format) accounts#create +# new_team_account GET /teams/:team_id/account/new(.:format) accounts#new +# edit_team_account GET /teams/:team_id/account/edit(.:format) accounts#edit +# GET /teams/:team_id/account(.:format) accounts#show +# PUT /teams/:team_id/account(.:format) accounts#update +# DELETE /teams/:team_id/account(.:format) accounts#destroy +# teams GET /teams(.:format) teams#index +# POST /teams(.:format) teams#create +# new_team GET /teams/new(.:format) teams#new +# edit_team GET /teams/:id/edit(.:format) teams#edit +# team GET /teams/:id(.:format) teams#show +# PUT /teams/:id(.:format) teams#update +# DELETE /teams/:id(.:format) teams#destroy +# leaderboard GET /leaderboard(.:format) teams#leaderboard +# employers GET /employers(.:format) teams#upgrade +# unlink_github POST /github/unlink(.:format) users#unlink_provider {:provider=>"github"} +# GET /github/:username(.:format) users#show {:provider=>"github"} +# unlink_twitter POST /twitter/unlink(.:format) users#unlink_provider {:provider=>"twitter"} +# GET /twitter/:username(.:format) users#show {:provider=>"twitter"} +# unlink_forrst POST /forrst/unlink(.:format) users#unlink_provider {:provider=>"forrst"} +# GET /forrst/:username(.:format) users#show {:provider=>"forrst"} +# unlink_dribbble POST /dribbble/unlink(.:format) users#unlink_provider {:provider=>"dribbble"} +# GET /dribbble/:username(.:format) users#show {:provider=>"dribbble"} +# unlink_linkedin POST /linkedin/unlink(.:format) users#unlink_provider {:provider=>"linkedin"} +# GET /linkedin/:username(.:format) users#show {:provider=>"linkedin"} +# unlink_codeplex POST /codeplex/unlink(.:format) users#unlink_provider {:provider=>"codeplex"} +# GET /codeplex/:username(.:format) users#show {:provider=>"codeplex"} +# unlink_bitbucket POST /bitbucket/unlink(.:format) users#unlink_provider {:provider=>"bitbucket"} +# GET /bitbucket/:username(.:format) users#show {:provider=>"bitbucket"} +# unlink_stackoverflow POST /stackoverflow/unlink(.:format) users#unlink_provider {:provider=>"stackoverflow"} +# GET /stackoverflow/:username(.:format) users#show {:provider=>"stackoverflow"} +# resume_uploads POST /resume_uploads(.:format) resume_uploads#create +# invite_users POST /users/invite(.:format) users#invite +# autocomplete_users GET /users/autocomplete(.:format) users#autocomplete +# status_users GET /users/status(.:format) users#status +# specialties_user POST /users/:id/specialties(.:format) users#specialties +# user_skills GET /users/:user_id/skills(.:format) skills#index +# POST /users/:user_id/skills(.:format) skills#create +# new_user_skill GET /users/:user_id/skills/new(.:format) skills#new +# edit_user_skill GET /users/:user_id/skills/:id/edit(.:format) skills#edit +# user_skill GET /users/:user_id/skills/:id(.:format) skills#show +# PUT /users/:user_id/skills/:id(.:format) skills#update +# DELETE /users/:user_id/skills/:id(.:format) skills#destroy +# user_highlights GET /users/:user_id/highlights(.:format) highlights#index +# POST /users/:user_id/highlights(.:format) highlights#create +# new_user_highlight GET /users/:user_id/highlights/new(.:format) highlights#new +# edit_user_highlight GET /users/:user_id/highlights/:id/edit(.:format) highlights#edit +# user_highlight GET /users/:user_id/highlights/:id(.:format) highlights#show +# PUT /users/:user_id/highlights/:id(.:format) highlights#update +# DELETE /users/:user_id/highlights/:id(.:format) highlights#destroy +# user_endorsements GET /users/:user_id/endorsements(.:format) endorsements#index +# POST /users/:user_id/endorsements(.:format) endorsements#create +# new_user_endorsement GET /users/:user_id/endorsements/new(.:format) endorsements#new +# edit_user_endorsement GET /users/:user_id/endorsements/:id/edit(.:format) endorsements#edit +# user_endorsement GET /users/:user_id/endorsements/:id(.:format) endorsements#show +# PUT /users/:user_id/endorsements/:id(.:format) endorsements#update +# DELETE /users/:user_id/endorsements/:id(.:format) endorsements#destroy +# user_pictures GET /users/:user_id/pictures(.:format) pictures#index +# POST /users/:user_id/pictures(.:format) pictures#create +# new_user_picture GET /users/:user_id/pictures/new(.:format) pictures#new +# edit_user_picture GET /users/:user_id/pictures/:id/edit(.:format) pictures#edit +# user_picture GET /users/:user_id/pictures/:id(.:format) pictures#show +# PUT /users/:user_id/pictures/:id(.:format) pictures#update +# DELETE /users/:user_id/pictures/:id(.:format) pictures#destroy +# user_follows GET /users/:user_id/follows(.:format) follows#index +# POST /users/:user_id/follows(.:format) follows#create +# new_user_follow GET /users/:user_id/follows/new(.:format) follows#new +# edit_user_follow GET /users/:user_id/follows/:id/edit(.:format) follows#edit +# user_follow GET /users/:user_id/follows/:id(.:format) follows#show +# PUT /users/:user_id/follows/:id(.:format) follows#update +# DELETE /users/:user_id/follows/:id(.:format) follows#destroy +# user_bans POST /users/:user_id/bans(.:format) bans#create +# user_unbans POST /users/:user_id/unbans(.:format) unbans#create +# users GET /users(.:format) users#index +# POST /users(.:format) users#create +# new_user GET /users/new(.:format) users#new +# edit_user GET /users/:id/edit(.:format) users#edit +# user GET /users/:id(.:format) users#show +# PUT /users/:id(.:format) users#update +# DELETE /users/:id(.:format) users#destroy +# clear_provider GET /clear/:id/:provider(.:format) users#clear_provider +# refresh GET /refresh/:username(.:format) users#refresh +# random_accomplishment GET /nextaccomplishment(.:format) highlights#random +# add_skill GET /add-skill(.:format) skills#create +# blog GET /blog(.:format) blog_posts#index +# blog_post GET /blog/:id(.:format) blog_posts#show +# atom GET /articles.atom(.:format) blog_posts#index {:format=>:atom} +# signin GET /signin(.:format) sessions#signin +# signout GET /signout(.:format) sessions#destroy +# sign_out GET /goodbye(.:format) sessions#destroy +# random_wall GET /roll-the-dice(.:format) users#randomize +# GET /providers/:provider/:username(.:format) provider_user_lookups#show +# GET|POST|PATCH|DELETE /404(.:format) errors#not_found +# GET|POST|PATCH|DELETE /422(.:format) errors#unacceptable +# GET|POST|PATCH|DELETE /500(.:format) errors#internal_error +# badge GET /:username(.:format) users#show +# user_achievement GET /:username/achievements/:id(.:format) achievements#show +# GET /:username/endorsements.json(.:format) endorsements#show +# followers GET /:username/followers(.:format) follows#index {:type=>:followers} +# following GET /:username/following(.:format) follows#index {:type=>:following} +# callbacks_hawt_feature POST /callbacks/hawt/feature(.:format) callbacks/hawt#feature +# callbacks_hawt_unfeature POST /callbacks/hawt/unfeature(.:format) callbacks/hawt#unfeature +# admin_root GET /admin(.:format) admin#index +# admin_teams GET /admin/teams(.:format) admin#teams +# admin_sections_teams GET /admin/teams/sections/:num_sections(.:format) admin#sections_teams +# admin_section_teams GET /admin/teams/section/:section(.:format) admin#section_teams +# admin_sidekiq_web /admin/sidekiq Sidekiq::Web +# latest_comments GET /comments(.:format) comments#index # Coderwall::Application.routes.draw do @@ -293,7 +294,7 @@ resources :protips, :path => '/p' do collection do - get ':id/:slug' => 'protips#show', as: :slug, :constraints => {:slug => /(?!.*?edit).*/} + get ':id/:slug' => 'protips#show', as: :slug, :constraints => {:slug => /(?!.*?edit).*/} get 'random' get 'search' => 'protips#search', as: :search post 'search' => 'protips#search' @@ -461,6 +462,9 @@ get '/providers/:provider/:username' => 'provider_user_lookups#show' + match '/404' => 'errors#not_found', via: [ :get, :post, :patch, :delete ] + match "/422" => "errors#unacceptable", via: [ :get, :post, :patch, :delete ] + match "/500" => "errors#internal_error", via: [ :get, :post, :patch, :delete ] constraints ->(params, _) { params[:username] != 'admin' } do get '/:username' => 'users#show', as: :badge diff --git a/spec/features/errors/internal_error_spec.rb b/spec/features/errors/internal_error_spec.rb new file mode 100644 index 00000000..383f1578 --- /dev/null +++ b/spec/features/errors/internal_error_spec.rb @@ -0,0 +1,22 @@ +require "rails_helper" + +feature "Custom 500 Page" do + before(:all) do + Rails.application.config.action_dispatch.show_exceptions = true + Rails.application.config.consider_all_requests_local = false + end + + after(:all) do + Rails.application.config.action_dispatch.show_exceptions = false + Rails.application.config.consider_all_requests_local = true + end + + scenario 'User is presented 500 page when an exception is raised' do + allow(User).to receive(:find_by_username!).and_raise(StandardError) + + visit '/user_causes_500_error' + + expect(page). + to have_content('Coderwall had an issue but hold on to your localhosts') + end +end diff --git a/spec/features/errors/not_found_spec.rb b/spec/features/errors/not_found_spec.rb new file mode 100644 index 00000000..7bc89934 --- /dev/null +++ b/spec/features/errors/not_found_spec.rb @@ -0,0 +1,25 @@ +require "rails_helper" + +feature "Custom 404 Page" do + before(:all) do + Rails.application.config.action_dispatch.show_exceptions = true + Rails.application.config.consider_all_requests_local = false + end + + after(:all) do + Rails.application.config.action_dispatch.show_exceptions = false + Rails.application.config.consider_all_requests_local = true + end + + scenario 'user is presented 404 page when they visit invalid path' do + visit '/fake/path/doesnt/match/route' + + expect(page).to have_content('Uh oh, something went wrong!') + end + + scenario 'user is presented 404 page when then visit a bad user path' do + visit '/not_a_real_username' + + expect(page).to have_content('Uh oh, something went wrong!') + end +end