레일즈에서 404로 리디렉션하는 방법은 무엇입니까?
저는 레일즈에서 404페이지를 '가짜'하고 싶습니다.PHP에서는 다음과 같은 오류 코드가 포함된 헤더를 보냅니다.
header("HTTP/1.0 404 Not Found");
레일즈는 어떻게 된 거지?
직접 렌더링하지 그럴 이유가 이 이 내장되어 . 404 접직지하마십시오링더렌를마▁don. Rails에는 이미 이 기능이 내장되어 있습니다.404페이지를 , 404페이지를 .render_404
또는 또방법(는)not_found
내가 말한 바와 같이)에ApplicationController
와 같이: 과같이다음:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
레도핸링을 합니다.AbstractController::ActionNotFound
,그리고.ActiveRecord::RecordNotFound
같은 방법.
이렇게 하면 다음과 같은 두 가지 작업을 더 잘 수행됩니다.
레일즈의 내장 기능을 사용합니다.rescue_from
핸들러가 404 페이지를 렌더링하고 2) 코드 실행을 방해하여 다음과 같은 좋은 작업을 수행할 수 있습니다.
user = User.find_by_email(params[:email]) or not_found
user.do_something!
위험한 조건문을 작성하지 않아도 됩니다.
보너스로, 그것은 또한 시험에서 다루기 매우 쉽습니다.예를 들어, rspec 통합 검정에서는 다음과 같이 합니다.
# RSpec 1
lambda {
visit '/something/you/want/to/404'
}.should raise_error(ActionController::RoutingError)
# RSpec 2+
expect {
get '/something/you/want/to/404'
}.to raise_error(ActionController::RoutingError)
그리고 미니테스트:
assert_raises(ActionController::RoutingError) do
get '/something/you/want/to/404'
end
또는 컨트롤러 작업에서 레일 렌더 404의 자세한 정보를 찾을 수 없습니다.
HTTP 404 상태
헤더를 헤더를 사용하면 됩니다.: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
작업에서 오류 페이지를 렌더링하고 중지하려면 반환문을 사용하십시오.
def action
render_404 and return if params[:something].blank?
# here the code that will never be executed
end
액티브레코드와 HTTP 404
Rails는 "Rails" "ActiveRecord"와 오류를 합니다.ActiveRecord::RecordNotFound
404 오류 페이지를 표시합니다.
당신이 직접 이 행동을 구출할 필요가 없다는 뜻입니다.
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
검사를 레일즈에 위임하여 단순화할 수 있습니다.그냥 뱅 버전을 사용하세요.
def show
user = User.find_by_email!(params[:email])
# ...
end
Steven Soroka가 제출한 새로 선택한 답변이 가깝지만 완료되지 않았습니다.테스트 자체는 이것이 진정한 404를 반환하지 않는다는 사실을 숨깁니다. 즉, 200 - "성공" 상태를 반환합니다.원래 답변은 더 가까웠지만 실패가 발생하지 않은 것처럼 레이아웃을 렌더링하려고 시도했습니다.이렇게 하면 모든 문제가 해결됩니다.
render :text => 'Not Found', :status => '404'
다음은 RSpec 및 Shoulda matchers를 사용하여 404를 반환할 것으로 예상되는 것에 대한 일반적인 테스트 세트입니다.
describe "user view" do
before do
get :show, :id => 'nonsense'
end
it { should_not assign_to :user }
it { should respond_with :not_found }
it { should respond_with_content_type :html }
it { should_not render_template :show }
it { should_not render_with_layout }
it { should_not set_the_flash }
end
이 건전한 편집증을 통해 다른 모든 것이 평화로워 보일 때 콘텐츠 유형의 불일치를 발견할 수 있었습니다 :) 할당된 변수, 응답 코드, 응답 콘텐츠 유형, 템플릿 렌더링, 레이아웃 렌더링, 플래시 메시지 등 모든 요소를 확인합니다.
엄격하게 html인 응용프로그램에 대한 내용 유형 검사를 건너뜁니다.가끔씩.결국, "회의론자가 모든 서랍을 확인한다" :)
http://dilbert.com/strips/comic/1998-01-20/
참고: 컨트롤러에서 발생하는 문제, 즉 "should_raise"에 대한 테스트는 권장하지 않습니다.당신이 관심을 갖는 것은 출력입니다.위의 테스트를 통해 다양한 솔루션을 시도할 수 있으며, 솔루션이 예외를 발생시키든 특수 렌더링을 발생시키든 테스트는 동일하게 유지됩니다.
렌더 파일을 사용할 수도 있습니다.
render file: "#{Rails.root}/public/404.html", layout: false, status: 404
레이아웃 사용 여부를 선택할 수 있는 위치입니다.
다른 옵션은 예외를 사용하여 제어하는 것입니다.
raise ActiveRecord::RecordNotFound, "Record not found."
오류 처리기가 미들웨어로 이동되었기 때문에 선택한 답변이 Rails 3.1+에서 작동하지 않습니다(github 문제 참조).
여기 제가 찾은 해결책이 있습니다. 제가 꽤 만족하는 것이죠.
ApplicationController
:
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.rb
:
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에 대해 다른 견해를 가지고 있습니다.
이것들이 당신을 도울 것입니다...
응용 프로그램 컨트롤러
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
보기/오류/오류_404.208.햄
.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
routes.rb
get '*unmatched_route', to: 'main#not_found'
main_controller.rb
def not_found
render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false
end
<%= render file: 'public/404', status: 404, formats: [:html] %>
이것을 404 오류 페이지에 렌더링할 페이지에 추가하기만 하면 완료됩니다.
저는 관리자가 아닌 로그인한 사용자를 위해 '일반' 404를 던지고 싶었습니다. 그래서 저는 Rails 5에 다음과 같습니다.
class AdminController < ApplicationController
before_action :blackhole_admin
private
def blackhole_admin
return if current_user.admin?
raise ActionController::RoutingError, 'Not Found'
rescue ActionController::RoutingError
render file: "#{Rails.root}/public/404", layout: false, status: :not_found
end
end
ActionController::RoutingError('not found')
인증되지 않은 사용자의 경우 이 오류는 현실을 반영하지 않습니다. 경로가 발견되었고 사용자가 인증되지 않았습니다.
우연히 알게 되었고 어떤 경우에는 이것이 언급된 문제에 대한 보다 우아한 해결책이라고 생각합니다.
# application.rb
config.action_dispatch.rescue_responses = {
'UnauthenticatedError' => :not_found
}
# my_controller.rb
before_action :verify_user_authentication
def verify_user_authentication
raise UnauthenticatedError if !user_authenticated?
end
이 접근 방식의 장점은 다음과 같습니다.
- 오류 처리 미들웨어처럼 .
ActionController::RoutingError
에서 더 있는 . - rescue_response 해시에서 지정한 대로 상태를 올바르게 설정합니다(이 경우 404 - not_found).
- 당신은 그것을 쓸 필요가 없습니다.
not_found
모든 곳에서 사용할 수 있어야 하는 방법.
오류 처리를 테스트하려면 다음과 같은 작업을 수행할 수 있습니다.
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
다양한 404를 다양한 방식으로 처리하려면 컨트롤러에서 이를 파악하는 것이 좋습니다.이를 통해 서로 다른 사용자 그룹에서 생성된 404개의 수를 추적하고, 지원팀이 사용자와 상호 작용하여 무엇이 잘못되었는지, 사용자 환경의 어떤 부분을 조정해야 하는지, A/B 테스트 등을 수행할 수 있습니다.
여기에서는 기본 논리를 Application Controller에 배치했지만, 특정 컨트롤러에 배치할 수도 있으므로 컨트롤러 하나에 대한 특수 논리를 가질 수도 있습니다.
ENV와 함께 if를 사용하는 이유['RESCURE_404'], AR의 상승을 테스트할 수 있습니다.:RecordNotFound가 분리되어 있습니다.테스트에서 이 ENV 변수를 false로 설정할 수 있으며 rescue_from이 실행되지 않습니다.이렇게 하면 조건부 404 로직과 별도로 상승을 테스트할 수 있습니다.
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, with: :conditional_404_redirect if ENV['RESCUE_404']
private
def conditional_404_redirect
track_404(@current_user)
if @current_user.present?
redirect_to_user_home
else
redirect_to_front
end
end
end
언급URL : https://stackoverflow.com/questions/2385799/how-to-redirect-to-a-404-in-rails
'sourcecode' 카테고리의 다른 글
Oracle 테이블에 열 추가 (0) | 2023.06.08 |
---|---|
Oracle에서 문자열 날짜를 datetime으로 변환 (0) | 2023.06.08 |
워크스페이스를 로드할 때 "나쁜 매직넘버" 오류의 원인과 회피 방법은 무엇입니까? (0) | 2023.06.08 |
킷체리픽이 말하길 "...38c74d는 병합이지만 -m 옵션이 제공되지 않았습니다." (0) | 2023.06.08 |
주소 표시줄이 iOS/Android/Mobile Chrome을 숨길 때 배경 이미지 점프 (0) | 2023.06.08 |