Ich möchte eine 404-Seite in Rails "fälschen". In PHP würde ich einfach einen Header mit dem Fehlercode als solchen senden:
header("HTTP/1.0 404 Not Found");
Wie wird das mit Rails gemacht?
Ich möchte eine 404-Seite in Rails "fälschen". In PHP würde ich einfach einen Header mit dem Fehlercode als solchen senden:
header("HTTP/1.0 404 Not Found");
Wie wird das mit Rails gemacht?
Rendere 404 nicht selbst, es gibt keinen Grund dazu; Rails hat diese Funktionalität bereits eingebaut. Wenn Sie eine 404-Seite anzeigen wollen, erstellen Sie eine render_404
Methode (oder not_found
wie ich es nannte) in ApplicationController
wie diese:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
Rails verarbeitet auch AbstractController::ActionNotFound
y ActiveRecord::RecordNotFound
auf die gleiche Weise.
Das macht zwei Dinge besser:
1) Es verwendet die in Rails eingebaute rescue_from
Handler, um die 404-Seite zu rendern, und 2) es unterbricht die Ausführung Ihres Codes, so dass Sie nette Dinge tun können wie:
user = User.find_by_email(params[:email]) or not_found
user.do_something!
ohne hässliche bedingte Anweisungen schreiben zu müssen.
Außerdem ist es bei Tests sehr einfach zu handhaben. Zum Beispiel in einem rspec-Integrationstest:
# 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)
Und Minitest:
assert_raises(ActionController::RoutingError) do
get '/something/you/want/to/404'
end
ODER beziehen Sie weitere Informationen von Rails render 404 nicht gefunden von einer Controller-Aktion
Um einen 404-Header zurückzugeben, verwenden Sie einfach die :status
Option für die Rendering-Methode.
def action
# here the code
render :status => 404
end
Wenn Sie die 404-Standardseite rendern möchten, können Sie das Merkmal in einer Methode extrahieren.
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
und rufen Sie es in Ihrer Aktion auf
def action
# here the code
render_404
end
Wenn Sie möchten, dass die Aktion die Fehlerseite wiedergibt und beendet wird, verwenden Sie einfach eine return-Anweisung.
def action
render_404 and return if params[:something].blank?
# here the code that will never be executed
end
Denken Sie auch daran, dass Rails einige ActiveRecord-Fehler rettet, wie zum Beispiel die ActiveRecord::RecordNotFound
die Anzeige der 404-Fehlerseite.
Das bedeutet, dass Sie diese Aktion nicht selbst retten müssen.
def show
user = User.find(params[:id])
end
User.find
wirft ein ActiveRecord::RecordNotFound
wenn der Benutzer nicht existiert. Dies ist eine sehr leistungsfähige Funktion. Sehen Sie sich den folgenden Code an
def show
user = User.find_by_email(params[:email]) or raise("not found")
# ...
end
Sie können dies vereinfachen, indem Sie die Prüfung an Rails delegieren. Verwenden Sie einfach die Bang-Version.
def show
user = User.find_by_email!(params[:email])
# ...
end
Sie können auch die Renderdatei verwenden:
render file: "#{Rails.root}/public/404.html", layout: false, status: 404
Hier können Sie wählen, ob Sie das Layout verwenden möchten oder nicht.
Eine andere Möglichkeit ist die Verwendung der Ausnahmen zur Kontrolle:
raise ActiveRecord::RecordNotFound, "Record not found."
Die gewählte Antwort funktioniert nicht in Rails 3.1+, da der Error-Handler in eine Middleware verschoben wurde (siehe Github-Problem ).
Hier ist die Lösung, die ich gefunden habe und mit der ich ziemlich zufrieden bin.
En 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
und in application.rb
:
config.after_initialize do |app|
app.routes.append{ match '*a', :to => 'application#not_found' } unless config.consider_all_requests_local
end
Und in meinen Ressourcen (anzeigen, bearbeiten, aktualisieren, löschen):
@resource = Resource.find(params[:id]) or not_found
Dies könnte sicherlich verbessert werden, aber zumindest habe ich verschiedene Ansichten für not_found und internal_error, ohne die Kernfunktionen von Rails zu überschreiben.
Diese werden Ihnen helfen...
Anwendung Controller
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
Fehler-Controller
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
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.