如何在Rails中重定向到404?

我想在Rails中「僞造」 404頁面。 在PHP中,我只發送帶有錯誤代碼的標頭,以下所示: html

header("HTTP/1.0 404 Not Found");

Rails如何作到這一點? git


#1樓

因爲錯誤處理程序已移至中間件,所以所選答案在Rails 3.1+中不起做用(請參閱github issue )。 github

這是我很滿意的解決方案。 app

ApplicationControllerless

unless Rails.application.config.consider_all_requests_local
    rescue_from Exception, with: :handle_exception
  end

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

  def handle_exception(exception=nil)
    if exception
      logger = Logger.new(STDOUT)
      logger.debug "Exception Message: #{exception.message} \n"
      logger.debug "Exception Class: #{exception.class} \n"
      logger.debug "Exception Backtrace: \n"
      logger.debug exception.backtrace.join("\n")
      if [ActionController::RoutingError, ActionController::UnknownController, ActionController::UnknownAction].include?(exception.class)
        return render_404
      else
        return render_500
      end
    end
  end

  def render_404
    respond_to do |format|
      format.html { render template: 'errors/not_found', layout: 'layouts/application', status: 404 }
      format.all { render nothing: true, status: 404 }
    end
  end

  def render_500
    respond_to do |format|
      format.html { render template: 'errors/internal_server_error', layout: 'layouts/application', status: 500 }
      format.all { render nothing: true, status: 500}
    end
  end

並在application.rbide

config.after_initialize do |app|
  app.routes.append{ match '*a', :to => 'application#not_found' } unless config.consider_all_requests_local
end

在個人資源(顯示,編輯,更新,刪除)中: 佈局

@resource = Resource.find(params[:id]) or not_found

固然能夠改善這一點,可是至少在不覆蓋Rails核心功能的狀況下,我對not_found和internal_error擁有不一樣的見解。 測試


#2樓

這些將幫助您... spa

應用控制器 debug

class ApplicationController < ActionController::Base
  protect_from_forgery
  unless Rails.application.config.consider_all_requests_local             
    rescue_from ActionController::RoutingError, ActionController::UnknownController, ::AbstractController::ActionNotFound, ActiveRecord::RecordNotFound, with: lambda { |exception| render_error 404, exception }
  end

  private
    def render_error(status, exception)
      Rails.logger.error status.to_s + " " + exception.message.to_s
      Rails.logger.error exception.backtrace.join("\n") 
      respond_to do |format|
        format.html { render template: "errors/error_#{status}",status: status }
        format.all { render nothing: true, status: status }
      end
    end
end

錯誤控制器

class ErrorsController < ApplicationController
  def error_404
    @not_found_path = params[:not_found]
  end
end

views / errors / error_404.html.haml

.site
  .services-page 
    .error-template
      %h1
        Oops!
      %h2
        404 Not Found
      .error-details
        Sorry, an error has occured, Requested page not found!
        You tried to access '#{@not_found_path}', which is not a valid page.
      .error-actions
        %a.button_simple_orange.btn.btn-primary.btn-lg{href: root_path}
          %span.glyphicon.glyphicon-home
          Take Me Home

#3樓

要測試錯誤處理,您能夠執行如下操做:

feature ErrorHandling do
  before do
    Rails.application.config.consider_all_requests_local = false
    Rails.application.config.action_dispatch.show_exceptions = true
  end

  scenario 'renders not_found template' do
    visit '/blah'
    expect(page).to have_content "The page you were looking for doesn't exist."
  end
end

#4樓

HTTP 404狀態

要返回404標頭,只需對render方法使用:status選項。

def action
  # here the code

  render :status => 404
end

若是要呈現標準404頁面,則可使用方法提取功能。

def render_404
  respond_to do |format|
    format.html { render :file => "#{Rails.root}/public/404", :layout => false, :status => :not_found }
    format.xml  { head :not_found }
    format.any  { head :not_found }
  end
end

並在行動中稱呼它

def action
  # here the code

  render_404
end

若是要使操做呈現錯誤頁面並中止,只需使用return語句便可。

def action
  render_404 and return if params[:something].blank?

  # here the code that will never be executed
end

ActiveRecord和HTTP 404

還請記住,Rails會挽救一些ActiveRecord錯誤,例如顯示404錯誤頁面的ActiveRecord::RecordNotFound

這意味着您無需本身挽救該動做

def show
  user = User.find(params[:id])
end

當用戶不存在時, User.find引起ActiveRecord::RecordNotFound 。 這是一個很是強大的功能。 看下面的代碼

def show
  user = User.find_by_email(params[:email]) or raise("not found")
  # ...
end

您能夠經過將檢查委託給Rails來簡化。 只需使用爆炸版本。

def show
  user = User.find_by_email!(params[:email])
  # ...
end

#5樓

您還可使用渲染文件:

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

您能夠選擇是否使用佈局的位置。

另外一種選擇是使用「異常」來控制它:

raise ActiveRecord::RecordNotFound, "Record not found."
相關文章
相關標籤/搜索