Dies ist das zweite Projekt, in dem Sie lernen, wie man wie Rubin schreibt, indem Sie die Definition der Rails-Methode interpretieren. Das Thema ist diesmal redirect_to
# File actionpack/lib/action_controller/metal/redirecting.rb, line 56
def redirect_to(options = {}, response_status = {})
raise ActionControllerError.new("Cannot redirect to nil!") unless options
raise AbstractController::DoubleRenderError if response_body
self.status = _extract_redirect_to_status(options, response_status)
self.location = _compute_redirect_to_location(request, options)
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
end
def redirect_to(options = {}, response_status = {})
Nimmt zwei Argumente. In beiden Fällen wird ein leerer Hash zugewiesen, wenn kein Argument übergeben wird.
raise ActionControllerError.new("Cannot redirect to nil!") unless options
Fehler auslösen, wenn die Optionen leer sind. Übrigens behandelt Ruby alles außer false und nil als true, sodass ein leerer Hash {} keinen Fehler verursacht. Ein Fehler tritt auf, wenn der Benutzer es wagt, nil / false zuzuweisen.
raise AbstractController::DoubleRenderError if response_body
Ein Fehler tritt auf, wenn Sie bereits eine HTTP-Antwort erhalten haben. Ich weiß nicht, wie response_body hier zugewiesen wird, aber es scheint einen Fehler zurückzugeben, wenn mehrere HTTP-Kommunikationen gleichzeitig ausgetauscht werden.
self.status = _extract_redirect_to_status(options, response_status)
Auch diesmal ist eine neue Methode herausgekommen.
#Fileactionpack/lib/action_controller/metal/redirecting.rb, line 117
def _extract_redirect_to_status(options, response_status)
if options.is_a?(Hash) && options.key?(:status)
Rack::Utils.status_code(options.delete(:status))
elsif response_status.key?(:status)
Rack::Utils.status_code(response_status[:status])
else
302
end
end
if options.is_a?(Hash) && options.key?(:status)
Ein Punkt der if-Bedingung is_a? Methode ist der Typ, in dem der Typ des Empfängers (hier "Optionen") in Klammern angegeben ist. Eine Methode, die true zurückgibt, wenn sie übereinstimmt (hier "Hash").
Die beiden Elemente Schlüssel? der if-Bedingung sind die Schlüssel, deren Namen in Klammern angegeben sind. Eine Methode, die true zurückgibt, wenn dies der Fall ist.
Mit anderen Worten, wenn das an redirect_to übergebene Argument ein Hash ist und den Schlüsselstatus hat, wird der Inhalt der if-Anweisung ausgeführt. Wie Sie im eingangs erwähnten Rails-Dokument sehen können
redirect_to post_url(@post), status: :found, notice: "Pay attention to the road"
redirect_to post_url(@post), status: 301, flash: { updated_post_id: @post.id }
Status ist ein Parametersatz des Programmierers, der die Methode redirect_to verwendet. Während Sie es lesen, können Sie sehen, welche Rolle die Parameter spielen.
Rack::Utils.status_code(options.delete(:status))
Rack ist eine Gruppe von Programmen, die als Vermittler zwischen Rails-Anwendungen und Anwendungsservern fungieren. (Middleware genannt) status_code ist eine Methode, die in einer Bibliothek namens Utils definiert ist.
Der Wert, der dem Optionsschlüsselstatus von der Löschmethode zugewiesen wurde, wird an die status_code-Methode übergeben.
def status_code(status)
if status.is_a?(Symbol)
SYMBOL_TO_STATUS_CODE[status] || 500
else
status.to_i
end
end
Diese Methode ist nur eine Methode zum Anzeigen des Statuswerts. Es heißt SYMBOL_TO_STATUS_CODE nur, wenn es von Symbol (bestimmt durch is_a) übergeben wird. Der in Rack :: Utils definierte Konvertierungs-Hash wird verwendet.
Die Definition selbst
SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message|
[message.downcase.gsub(/\s|-|'/, '_').to_sym, code]
}.flatten]
Es sieht aus wie das. Der Hash HTTP_STATUS_CODES wird ebenfalls durch diesen Code in Rack :: Utils {: HTTP-Statusname definiert In ein Hash-Array mit dem Namen => HTTP-Statuscode} konvertieren.
Speziell
pry(main)> Rack::Utils::SYMBOL_TO_STATUS_CODE
=> {:continue=>100,
:switching_protocols=>101,
:processing=>102,
:early_hints=>103,
:ok=>200,
:created=>201,
:accepted=>202,
:non_authoritative_information=>203,
:no_content=>204,
:reset_content=>205,
:partial_content=>206,
:multi_status=>207,
:already_reported=>208,
:im_used=>226,
:multiple_choices=>300,
:moved_permanently=>301,
:found=>302,
:see_other=>303,
:not_modified=>304,
:use_proxy=>305,
:"(unused)"=>306,
:temporary_redirect=>307,
:permanent_redirect=>308,
:bad_request=>400,
:unauthorized=>401,
:payment_required=>402,
:forbidden=>403,
:not_found=>404,
:method_not_allowed=>405,
:not_acceptable=>406,
:proxy_authentication_required=>407,
:request_timeout=>408,
:conflict=>409,
:gone=>410,
:length_required=>411,
:precondition_failed=>412,
:payload_too_large=>413,
:uri_too_long=>414,
:unsupported_media_type=>415,
:range_not_satisfiable=>416,
:expectation_failed=>417,
:misdirected_request=>421,
:unprocessable_entity=>422,
:locked=>423,
:failed_dependency=>424,
:too_early=>425,
:upgrade_required=>426,
:precondition_required=>428,
:too_many_requests=>429,
:request_header_fields_too_large=>431,
:unavailable_for_legal_reasons=>451,
:internal_server_error=>500,
:not_implemented=>501,
:bad_gateway=>502,
:service_unavailable=>503,
:gateway_timeout=>504,
:http_version_not_supported=>505,
:variant_also_negotiates=>506,
:insufficient_storage=>507,
:loop_detected=>508,
:bandwidth_limit_exceeded=>509,
:not_extended=>510,
:network_authentication_required=>511}
#Führen Sie es auf der Rails-Konsole aus.
Mit anderen Worten, wenn Sie zur Definition von status_code zurückkehren
SYMBOL_TO_STATUS_CODE[status] || 500
In status :: not_found wird "404" zurückgegeben. Wenn kein entsprechender Artikel vorhanden ist, wird "500" zurückgegeben.
Wenn ein Wert wie "404" in den Optionen [: status] anstelle des Symbols angezeigt wird, gibt die 4. bis 5. Zeile den Wert im Ganzzahlformat zurück.
else
status.to_i
end
(Erneut veröffentlichen)
#Fileactionpack/lib/action_controller/metal/redirecting.rb, line 117
def _extract_redirect_to_status(options, response_status)
if options.is_a?(Hash) && options.key?(:status)
Rack::Utils.status_code(options.delete(:status))
elsif response_status.key?(:status)
Rack::Utils.status_code(response_status[:status])
else
302
end
end
Bisher habe ich in der dritten Zeile gelesen, was ich mache.
elsif response_status.key?(:status)
Die key? -Methode macht diese bedingte Anweisung wahr, wenn das Argument response_status einen Schlüsselstatus hat. Die auszuführende Methode ist dieselbe wie zuvor.
Es scheint sich um eine if-Verzweigung zu handeln, mit der der HTTP-Status korrekt zurückgegeben werden kann, unabhängig davon, ob der Statuswert in options oder response_status übergeben wird.
Wenn der zurückzugebende HTTP-Status nicht übergeben wird Die else-Anweisung in den Zeilen 6-7 gibt 302 zurück. (Es bedeutet "Weiterleitungsverarbeitung".)
redirect_to (Erneut veröffentlichen)
# File actionpack/lib/action_controller/metal/redirecting.rb, line 56
def redirect_to(options = {}, response_status = {})
raise ActionControllerError.new("Cannot redirect to nil!") unless options
raise AbstractController::DoubleRenderError if response_body
self.status = _extract_redirect_to_status(options, response_status)
self.location = _compute_redirect_to_location(request, options)
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
end
In der 4. Zeile habe ich beschlossen, den HTTP-Statuscode an die Benutzerseite zurückzugeben.
self.location = _compute_redirect_to_location(request, options)
Eine neue Schienenmethode ist angekommen. Die hier zugewiesene Anforderung ist das Objekt, das jedes Mal auf der Steuerung erstellt wird. Jeder Parameter der HTTP-Anforderung, die von der Benutzerseite an die Rails-Anwendungsseite gesendet wird, wird gespeichert.
Welche Parameter gibt es? [Rails Guide](https://railsguides.jp/action_controller_overview.html#request%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3 % 83% 88% E3% 81% A8Response% E3% 82% AA% E3% 83% 96% E3% 82% B8% E3% 82% A7% E3% 82% AF% E3% 83% 88) Ich bin.
Sie können den Wert wie request.host abrufen.
Die Definition selbst erfolgt im ActionDispatch :: Request-Modell. Die für dieses Modell verfügbaren Methoden sind hier aufgelistet (https://api.rubyonrails.org/classes/ActionDispatch/Request.html).
# File actionpack/lib/action_controller/metal/redirecting.rb, line 96
def _compute_redirect_to_location(request, options) #:nodoc:
case options
# The scheme name consist of a letter followed by any combination of
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
# characters; and is terminated by a colon (":").
# See https://tools.ietf.org/html/rfc3986#section-3.1
# The protocol relative scheme starts with a double slash "//".
when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/
options
when String
request.protocol + request.host_with_port + options
when Proc
_compute_redirect_to_location request, instance_eval(&options)
else
url_for(options)
end.delete("\00\\r\n")
end
Diese Methode generiert die URL, zu der umgeleitet werden soll. Die bedingte Verzweigung durch die case-Anweisung erfolgt durch den Inhalt der Optionen.
when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/
options
http://のように先頭に○○://とつく文字列のときに、この条件がtrueとなります。 Da davon ausgegangen wird, dass es sich um eine URL handelt, wird der Wert der Optionen unverändert zurückgegeben.
when String
request.protocol + request.host_with_port + options
Wird aufgerufen, wenn options eine Zeichenfolge ist. Die URL wird basierend auf dem Anforderungsobjekt generiert, in dem die Anforderungsinformationen der zuvor eingeführten Benutzerseite gespeichert sind. http: // und https: // werden im Protokoll gespeichert. host_with_port generiert Hosts nach //. Schließlich werden Optionen angegeben.
Die Methode host_with_port ist eine einfache Methode, die die im Anforderungsobjekt gespeicherten Eigenschaften = host und port_string aufruft und als Zeichenfolge kombiniert.
# File actionpack/lib/action_dispatch/http/url.rb, line 250
def host_with_port
"#{host}#{port_string}"
end
when Proc
_compute_redirect_to_location request, instance_eval(&options)
Was ist Proc
Ein prozedurales Objekt, das einen Block mit einem Kontext objektiviert (lokaler Variablenbereich oder Stapelrahmen). (https://docs.ruby-lang.org/ja/latest/class/Proc.html)[https://docs.ruby-lang.org/ja/latest/class/Proc.html]
redirect_to kann im Blockformat verwendet werden, und es ist in Ordnung zu erkennen, dass es in diesen Zweig eintritt, wenn ein Block angegeben wird.
Zum Beispiel
get 'jokes/:number', to: redirect { |params, request|
path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")
"http://#{request.host_with_port}/#{path}"
}
Sie können so etwas schreiben.
Wenn der Block aufgerufen wird, wird die Methode _compute_redirect_to_location rekursiv aufgerufen. Für Anfänger ist Wiederholung der Aufruf derselben Methode innerhalb einer Methode. Zum Beispiel
def method
method
end
Es ist wie geformt. (In diesem Fall handelt es sich um eine Endlosschleife. Normalerweise wird sie so geschrieben, dass sie nicht unendlich mit if branch usw. wiederholt wird.)
(Erneut veröffentlichen)
\_compute_redirect_to_location request, instance_eval(&options)
instance_eval (& options) wird dem zweiten Term der Methode \ _compute_redirect_to_location (request, options) zugewiesen.
Vor den Optionen steht ein &, was bedeutet, dass ein Block zugewiesen wird. instance_eval ist eine Methode, die die Ausgabe zurückgibt, wenn der Code im Block ausgeführt wird.
Betrachten wir das vorherige Beispiel (Erneut veröffentlichen)
get 'jokes/:number', to: redirect { |params, request|
path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")
"http://#{request.host_with_port}/#{path}"
}
In diesem Fall wird der Code in der 2. und 3. Zeile ausgeführt, und als Ergebnis wird die URL, die mit http: // in der 3. Zeile beginnt, als Zeichenfolge zurückgegeben. Mit anderen Worten Die URL wird der Methode \ _compute_redirect_to_location zugewiesen. Die case-Anweisung wird aufgerufen und verzweigt sich zu den oben genannten Bedingungen in der 9. bis 10. Zeile. (Erneut veröffentlichen)
when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/
options
else
url_for(options)
Um die bisherigen Bedingungen zusammenzufassen http://~といった具体的なURL、ファイル名を指す文字列、ブロックについて分岐されてきたが、いずれにも該当しない場合はこのelse文の内容が実行されることになります。
Was hier herauskommt, ist die url_for-Methode, die auch in link_to verwendet wurde.
def url_for(options)
if options[:only_path]
path_for options
else
full_url_for options
end
end
url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :port => '8080'
# => 'http://somehost.org:8080/tasks/testing'
url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :anchor => 'ok', :only_path => true
# => '/tasks/testing#ok'
url_for :controller => 'tasks', :action => 'testing', :trailing_slash => true
# => 'http://somehost.org/tasks/testing/'
url_for :controller => 'tasks', :action => 'testing', :host => 'somehost.org', :number => '33'
# => 'http://somehost.org/tasks/testing?number=33'
(Zitat) Generieren Sie eine URL wie diese.
end.delete("\00\\r\n")
Löschen wird am Ende der case-Anweisung aufgerufen.
Da eine Zeichenfolge aufgerufen wird, unterscheidet sich das Verhalten von dem bisher aufgetretenen Löschen. Laut der Ruby-Referenz
delete(*strs) -> String Erzeugt eine Zeichenfolge und gibt sie zurück, wobei die in strs enthaltenen Zeichen entfernt werden.
Die Referenz enthält auch einen Referenzartikel für das strs-Format. Ich bin mir nicht sicher, weil es weniger wichtig ist und ich es nicht verstehe. Da \ r und \ n Sonderzeichen sind, die "return" bzw. "line feed" darstellen, wird angenommen, dass sie die Bedeutung haben, diese mit url gemischten Zeichen zu löschen. Dann weiß ich nicht, was \ 00 \ ist, und vielleicht kann ich es von \ 0, 0, \, r, \ n trennen.
Bisher die Methode \ _compute_redirect_to_location.
redirect_to (Erneut veröffentlichen)
# File actionpack/lib/action_controller/metal/redirecting.rb, line 56
def redirect_to(options = {}, response_status = {})
raise ActionControllerError.new("Cannot redirect to nil!") unless options
raise AbstractController::DoubleRenderError if response_body
self.status = _extract_redirect_to_status(options, response_status)
self.location = _compute_redirect_to_location(request, options)
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
end
Zeile 4 bestimmt den HTTP-Statuscode, der nach der Umleitung an den Benutzer zurückgegeben werden soll. Die URL des Weiterleitungsziels wurde in der 5. Zeile festgelegt.
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
Entscheiden Sie nun, welche HTML-Daten an die Benutzerseite zurückgegeben werden sollen. Dieses HTML wird im Benutzerbrowser nicht angezeigt, da der Umleitungsprozess tatsächlich basierend auf dem Standortwert ausgeführt wird.
Hier wird der in self gespeicherte Wert als HTTP-Antwort an den Browser des Benutzers übergeben. Wenn Sie sich die URL der Location-Eigenschaft (Attribut) im HTTP-Header ansehen, stellt der Browser des Benutzers die Anforderung erneut.
Informationen zur Verarbeitung des Browsers finden Sie unter hier.
(Erneut veröffentlichen)
# File actionpack/lib/action_controller/metal/redirecting.rb, line 56
def redirect_to(options = {}, response_status = {})
raise ActionControllerError.new("Cannot redirect to nil!") unless options
raise AbstractController::DoubleRenderError if response_body
self.status = _extract_redirect_to_status(options, response_status)
self.location = _compute_redirect_to_location(request, options)
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
end
Wenn redirect_to aufgerufen wird
Ich fand, dass es die Aufgabe ist, die dafür erforderlichen Antwortdaten zu generieren, vorausgesetzt, dass die eigentliche Verarbeitung dem Client (dem vom Benutzer verwendeten Browser) überlassen bleibt, anstatt die Verarbeitung in dieser Methode durchzuführen.
Wenn Sie Ihr Verständnis für die Verarbeitung von Rails-Anwendungen und Middleware vertiefen, können Sie anscheinend eine kompliziertere Verarbeitung implementieren.
Recommended Posts