[RUBY] Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 10

Überblick

Dieser Artikel vertieft mein Verständnis, indem er einen Kommentarartikel zum Rails-Tutorial schreibt, um mein Wissen weiter zu festigen Es ist Teil meines Studiums. In seltenen Fällen kann es lächerliche oder falsche Inhalte enthalten. Bitte beachten Sie. Ich würde es begrüßen, wenn Sie mir implizit sagen könnten ...

Quelle Rails Tutorial 6. Ausgabe

Was ist in diesem Kapitel zu tun?

Da konnten wir die Benutzererstellung, Anmeldung und Speicherung von Anmeldeinformationen implementieren Erstellen Sie als Nächstes Funktionen zum Aktualisieren, Anzeigen und Löschen, die in den Benutzerressourcen unbeaufsichtigt blieben.

Benutzer aktualisieren

Bearbeiten Sie die Bearbeitungsaktion, um den Benutzer zu aktualisieren. Die neuen Aktionen des Sitzungscontrollers, die wir bisher implementiert haben Bereiten Sie ein Formular wie die neue Aktion des Benutzer-Controllers und vor Sie können die Aktion zum Senden des Eingabewerts des Formulars an die Aktualisierungsaktion implementieren. Natürlich kann der Benutzer es bearbeiten, aber unter Verwendung der bisher implementierten Authentifizierung Wir werden die Zugangskontrolle implementieren.

Formular bearbeiten

Die Bearbeitungsseite enthält die ID des Zielbenutzers in der URL ex) users/1/edit

Verwenden Sie diese Option, um den Benutzer aus der URL-ID zu extrahieren und in der Instanzvariablen zu speichern.

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

Geben Sie auf diese Weise das Objekt "@ user" als Modellobjekt im nächsten zu erstellenden Formular an.

erb:edit.html.erb


<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) do |f| %>
      <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name, class: 'form-control' %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit "Save changes", class: "btn btn-primary" %>
    <% end %>

    <div class="gravatar_edit">
      <%= gravatar_for @user %>
      <a href="https://gravatar.com/emails" target="_blank">change</a>
    </div>
  </div>
</div>

Wiederverwenden von _error_messages-Partials, um Fehlermeldungen anzuzeigen, wenn ungültige Werte in das Formular eingegeben werden.

Es gibt auch `target =" _ blank "` im Link-Teil von Gravatar, aber wenn Sie so schreiben, kann das Link-Ziel in einer neuen Registerkarte angezeigt werden.

Außerdem wird der aktuell in der Variablen @user enthaltene Wert automatisch in das Formulareingabefeld eingegeben. Es scheint, dass Rails die automatisch gespeicherten Attributinformationen abruft und anzeigt. Guu kompetent.

Mit Ausnahme des tatsächlich aus diesem Erb generierten HTML-Codes <input type="hidden" name="_method" value="patch"> Es gibt eine solche Beschreibung. Rails kann keine PATCH-Anforderung senden, bei der es sich um eine Aktualisierungsanforderung handelt, da der Webbrowser sie nicht senden kann. Durch Angabe eines Patches im ausgeblendeten Eingabefeld wird es als Pseudo-PATCH-Anforderung gefälscht.

Eine andere Sache, die Sie beachten sollten, ist, dass die neuen und Bearbeitungsaktionen fast denselben erb-Code verwenden. Warum Rails erkennen kann, ob es sich um einen neuen oder einen vorhandenen Benutzer handelt Dies liegt daran, dass die Methode `new_record?` Von ActiveRecord verwendet werden kann, um festzustellen, ob es neu oder vorhanden ist.

>> new_user = User.new
   (1.3ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil, password_digest: nil, remember_digest: nil>
>> user1 = User.first
  User Load (0.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "take", email: "[email protected]", created_at: "2020-06-14 02:57:10", updated_at: "2020-06-20 03:53:57", password_digest: [FILTERED], remember_digest: "$2a$12$tYO.HIfYezXpTk2zRp9s6uqJY4wUkPM28NfYuJ7vxq/...">
>> new_user.new_record?
=> true
>> user1.new_record?
=> false
>> 

Im eigentlichen erbform_Für Modellobjekte bei Verwendung mitnew_record?```Schauen Sie sich das Ergebnis von an Bestimmen Sie, ob es sich um einen Post oder einen Patch handelt.

Stellen Sie abschließend in der Navigationsleiste einen Link zur Bearbeitungsaktion ein. <li><%= link_to "settings", edit_user_path(current_user) %></li>

#####Übung 1.Da ich interessiert war, war der folgende Artikel hilfreich, da ich untersucht habe, welche Art von Sicherheitslücken es gibt, und ich werde ihn verlassen. https://webegins.com/target-blank/ "noopener"Super wichtig!

2.Der Formularteil ist in der neuen Ansicht und in der Bearbeitungsansicht nahezu identisch, und es gibt Unterschiede Es geht um den Text der Schaltfläche "Senden". Verwenden Sie daher die Bereitstellungsmethode, um den Textinhalt der Schaltfläche "Senden" zu ändern. Refactor alle zusammen in einem Teil.

erbb:_form.html.erb


    <%= form_with(model: @user, local: true) do |f| %>
      <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name, class: 'form-control' %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit yield(:btn_text), class: "btn btn-primary" %>
    <% end %>

erb:new.html.erb


<% provide(:title, 'Sign up') %>
<% provide(:btn_text, "Create my account") %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= render 'form' %>
  </div>
</div>

erb:edit.html.erb


<% provide(:title, "Edit user") %>
<% provide(:btn_text, "Save changes") %>
<h1>Update your profile</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= render 'form' %>
    <div class="gravatar_edit">
      <%= gravatar_for @user %>
      <a href="https://gravatar.com/emails" target="_blank" rel="noopener">change</a>
    </div>
  </div>
</div>

####Bearbeitungsfehler Wie bei der Benutzerregistrierung wird dies bei Bearbeitungsfehlern implementiert, wenn versucht wird, mit einem ungültigen Wert zu aktualisieren. Wir werden die Aktualisierungsaktion implementieren, aber es ist dasselbe wie das Erstellen eines Benutzers mithilfe von Parametern mit der Erstellungsaktion. Aktualisieren Sie mit den Parametern, die von der Bearbeitungsaktion gesendet wurden. Die Struktur ist ziemlich ähnlich. Natürlich ist es gefährlich, die DB direkt mit params zu aktualisieren, also diesmal auch StrongParameter(Zuvor definierter Benutzer_params Methode)verwenden.

  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      
    else
      render 'edit'
    end
  end

Im Moment mit Benutzermodellvalidierung_error_Nachrichten Weil es einen Teil gibt Bei ungültigen Werten wird ein Fehler zurückgegeben.

#####Übung 1.Scheitern. image.png

####Test, wenn die Bearbeitung fehlschlägt Erstellen Sie benutzerbearbeitungsbezogene Integrationstests. Dieses Mal werde ich, wie der Titel schon sagt, einen Test schreiben, wenn die Bearbeitung fehlschlägt. rails g integration_test user_edit

users_edit_test.rb


require 'test_helper'

class UserEditTest < ActionDispatch::IntegrationTest
  def setup 
    @user = users(:michael)
  end
  
  test "unsuccessful edit" do
    get edit_user_path(@user)
    assert_template 'users/edit'
    patch user_path(@user) , params:{user:{name: "",
                                           email: "foo@bar",
                                           password: "foo",
                                           password_confirmation: "bar"}}
    assert_template 'users/edit'
  end
end

1.Anforderung auf Bearbeitungsseite abrufen, prüfen, ob Bearbeitungsseite gezeichnet ist 2.Patch-Anfrage senden, ungültiger Wert zum Aktualisieren der Aktion 3.Überprüfen Sie, ob die Bearbeitungsseite neu gezeichnet wurde.

Es wird ein Test in der Reihenfolge von.

#####Übung 1. assert_select 'div.alert', "The form contains 4 errors."

####Erfolgreiche Bearbeitung mit TDD Dieses Mal werden wir die Operation zum Zeitpunkt des Erfolgs implementieren. Benutzer⁻ Das Bild funktioniert bereits, da es in Gravatar implementiert ist. name,email,Implementieren Sie die erfolgreiche Bearbeitung anderer Attribute wie z. B. des Kennworts.

Ein Test zum Schreiben eines Integrationstests vor dem Implementieren eines Features und zum Feststellen, ob das Feature akzeptabel ist, wenn das Feature implementiert wurde Wird als "Abnahmetest" bezeichnet. Lassen Sie uns tatsächlich eine erfolgreiche Bearbeitung mit TDD implementieren.

Es ist einfacher zu verstehen, ob Sie es implementieren, indem Sie sich auf den Test zum Zeitpunkt des Fehlers beziehen, den Sie zuvor implementiert haben.(Natürlich werde ich gültige Daten senden)

  test "successful edit" do
    get edit_user_path(@user)
    assert_template 'users/edit'
    name = "foo"
    email = "[email protected]"
    patch user_path(@user) , params:{user:{name: name,
                                           email: email,
                                           password: "",
                                           password_confirmation: ""}}
    
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal name, @user.name
    assert_equal email, @user.email
  end

Vertiefen Sie Ihr Verständnis, indem Sie Artikel mit Rails-Tutorial-Kommentaren schreiben, um dies sicherzustellen Es ist Teil meines Studiums. In seltenen Fällen kann es lächerliche oder falsche Inhalte enthalten. Bitte beachten Sie. Ich würde es begrüßen, wenn Sie mir implizit sagen könnten ...

Quelle Rails Tutorial 6. Ausgabe

###Was ist in diesem Kapitel zu tun? Da konnten wir die Benutzererstellung, Anmeldung und Speicherung von Anmeldeinformationen implementieren Erstellen Sie als Nächstes Funktionen zum Aktualisieren, Anzeigen und Löschen, die in den Benutzerressourcen unbeaufsichtigt blieben.

###Benutzer aktualisieren Bearbeiten Sie die Bearbeitungsaktion, um den Benutzer zu aktualisieren. Die neuen Aktionen des Sitzungscontrollers, die wir bisher implementiert haben Bereiten Sie ein Formular wie die neue Aktion des Benutzer-Controllers und vor Sie können die Aktion zum Senden des Eingabewerts des Formulars an die Aktualisierungsaktion implementieren. Natürlich kann der Benutzer es bearbeiten, aber unter Verwendung der bisher implementierten Authentifizierung Wir werden die Zugangskontrolle implementieren.

####Formular bearbeiten Die Bearbeitungsseite enthält die ID des Zielbenutzers in der URL ex) users/1/edit

Verwenden Sie diese Option, um den Benutzer aus der URL-ID zu extrahieren und in der Instanzvariablen zu speichern.

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

Auf diese Weise ist das nächste Formular, das Sie erstellen, ein Modellobjekt.@userGeben Sie das Objekt an.

erb:edit.html.erb


<% provide(:title, "Edit user") %>
<h1>Update your profile</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
     <%= form_with(model: @user, local: true) do |f| %>
      <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name, class: 'form-control' %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit "Save changes", class: "btn btn-primary" %>
    <% end %>

    <div class="gravatar_edit">
      <%= gravatar_for @user %>
      <a href="https://gravatar.com/emails" target="_blank">change</a>
    </div>
  </div>
</div>

Anzeigen einer Fehlermeldung bei Eingabe eines ungültigen Werts in das Formular_error_Nachrichten Teilweise wird wiederverwendet.

Auch im Link-Teil von Gravatartarget="_blank"Wenn Sie jedoch so schreiben, kann das Linkziel auf einer neuen Registerkarte angezeigt werden.

Weiterhin im Eingabefeld des Formulars@Der aktuell in der Benutzervariable enthaltene Wert wird automatisch eingegeben. Es scheint, dass Rails die automatisch gespeicherten Attributinformationen abruft und anzeigt. Guu kompetent.

Mit Ausnahme des tatsächlich aus diesem Erb generierten HTML-Codes <input type="hidden" name="_method" value="patch"> Es gibt eine solche Beschreibung. Rails kann keine PATCH-Anforderung senden, bei der es sich um eine Aktualisierungsanforderung handelt, da der Webbrowser sie nicht senden kann. Durch Angabe eines Patches im ausgeblendeten Eingabefeld wird es als Pseudo-PATCH-Anforderung gefälscht.

Eine andere Sache, die Sie beachten sollten, ist, dass die neuen und Bearbeitungsaktionen fast denselben erb-Code verwenden. Warum Rails erkennen kann, ob es sich um einen neuen oder einen vorhandenen Benutzer handelt Aktiver Rekordnew_record?Dies liegt daran, dass die Methode feststellen kann, ob sie neu oder vorhanden ist.

>> new_user = User.new
   (1.3ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil, password_digest: nil, remember_digest: nil>
>> user1 = User.first
  User Load (0.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "take", email: "[email protected]", created_at: "2020-06-14 02:57:10", updated_at: "2020-06-20 03:53:57", password_digest: [FILTERED], remember_digest: "$2a$12$tYO.HIfYezXpTk2zRp9s6uqJY4wUkPM28NfYuJ7vxq/...">
>> new_user.new_record?
=> true
>> user1.new_record?
=> false
>> 

Schauen Sie sich im tatsächlichen erb das Ergebnis von `new_record?` `Für das Modellobjekt an, wenn Sie` form_with "verwenden. Bestimmen Sie, ob es sich um einen Post oder einen Patch handelt.

Stellen Sie abschließend in der Navigationsleiste einen Link zur Bearbeitungsaktion ein. <li><%= link_to "settings", edit_user_path(current_user) %></li>

Übung
  1. Ich war neugierig und als Ergebnis der Untersuchung, welche Art von Schwachstellen es gibt, war der folgende Artikel hilfreich, also werde ich ihn verlassen. https://webegins.com/target-blank/ "noopener" super wichtig!

  2. Der Formularteil ist in der neuen Ansicht und in der Bearbeitungsansicht nahezu identisch. Es geht um den Text der Schaltfläche "Senden". Verwenden Sie daher die Bereitstellungsmethode, um den Textinhalt der Schaltfläche "Senden" zu ändern. Refactor alle zusammen in einem Teil.

erbb:_form.html.erb


   <%= form_with(model: @user, local: true) do |f| %>
      <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name, class: 'form-control' %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation, class: 'form-control' %>

      <%= f.submit yield(:btn_text), class: "btn btn-primary" %>
    <% end %>

erb:new.html.erb


<% provide(:title, 'Sign up') %>
<% provide(:btn_text, "Create my account") %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= render 'form' %>
  </div>
</div>

erb:edit.html.erb


<% provide(:title, "Edit user") %>
<% provide(:btn_text, "Save changes") %>
<h1>Update your profile</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= render 'form' %>
    <div class="gravatar_edit">
      <%= gravatar_for @user %>
      <a href="https://gravatar.com/emails" target="_blank" rel="noopener">change</a>
    </div>
  </div>
</div>

Bearbeitungsfehler

Wie bei der Benutzerregistrierung wird dies bei Bearbeitungsfehlern implementiert, wenn versucht wird, mit einem ungültigen Wert zu aktualisieren. Wir werden die Aktualisierungsaktion implementieren, aber es ist dasselbe wie das Erstellen eines Benutzers mithilfe von Parametern mit der Erstellungsaktion. Aktualisieren Sie mit den Parametern, die von der Bearbeitungsaktion gesendet wurden. Die Struktur ist ziemlich ähnlich. Natürlich ist es gefährlich, die Datenbank direkt mit Parametern zu aktualisieren, daher werden wir auch dieses Mal StrongParameter (zuvor definierte user_params-Methode) verwenden.

  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      
    else
      render 'edit'
    end
  end

Da zu diesem Zeitpunkt eine Benutzermodellvalidierung und _error_messages teilweise vorhanden sind Bei ungültigen Werten wird ein Fehler zurückgegeben.

Übung
  1. Scheitern. image.png

Test, wenn die Bearbeitung fehlschlägt

Erstellen Sie benutzerbearbeitungsbezogene Integrationstests. Dieses Mal werde ich, wie der Titel schon sagt, einen Test schreiben, wenn die Bearbeitung fehlschlägt. rails g integration_test user_edit

users_edit_test.rb


require 'test_helper'

class UserEditTest < ActionDispatch::IntegrationTest
  def setup 
    @user = users(:michael)
  end
  
  test "unsuccessful edit" do
    get edit_user_path(@user)
    assert_template 'users/edit'
    patch user_path(@user) , params:{user:{name: "",
                                           email: "foo@bar",
                                           password: "foo",
                                           password_confirmation: "bar"}}
    assert_template 'users/edit'
  end
end
  1. GET-Anforderung auf Bearbeitungsseite abrufen, prüfen, ob Bearbeitungsseite gezeichnet ist
  2. Senden Sie eine Patch-Anfrage mit einem ungültigen Wert, um die Aktion zu aktualisieren
  3. Überprüfen Sie, ob die Bearbeitungsseite neu gezeichnet wurde.

Es wird ein Test in der Reihenfolge von.

Übung

1. assert_select 'div.alert', "The form contains 4 errors."

Erfolgreiche Bearbeitung mit TDD

Dieses Mal werden wir die Operation zum Zeitpunkt des Erfolgs implementieren. Benutzer⁻ Das Bild funktioniert bereits, da es in Gravatar implementiert ist. Implementieren Sie die erfolgreiche Bearbeitung anderer Attribute wie Name, E-Mail-Adresse und Passwort.

Ein Test zum Schreiben eines Integrationstests vor dem Implementieren eines Features und zum Feststellen, ob das Feature akzeptabel ist, wenn das Feature implementiert wurde Wird als "Abnahmetest" bezeichnet. Lassen Sie uns tatsächlich eine erfolgreiche Bearbeitung mit TDD implementieren.

Es ist einfacher zu verstehen, ob Sie es implementieren, indem Sie sich auf den Test zum Zeitpunkt des Fehlers beziehen, den Sie zuvor implementiert haben. (Natürlich werde ich gültige Daten senden)

  test "successful edit" do
    get edit_user_path(@user)
    assert_template 'users/edit'
    name = "foo"
    email = "[email protected]"
    patch user_path(@user) , params:{user:{name: name,
                                           email: email,
                                           password: "",
                                           password_confirmation: ""}}
    
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal name, @user.name
    assert_equal email, @user.email
  end

Natürlich schlägt der Test fehl. Erstens werden keine Flash-Nachrichten implementiert. Sie haben keine Umleitung angegeben. Diese beiden werden erwischt. Und das Wichtigste. Da der Kennwortwert leer ist, wird die Validierung abgefangen und kann nicht normal aktualisiert werden.

Die beiden ersteren sind auf dieser Linie implementiert.

  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    
    end
  end

Zu diesem Zeitpunkt wird @ user.update bei der Validierung mit einem leeren Kennwort abgefangen und zu einer else-Anweisung verzweigt Der Test funktioniert auch nicht. Fügen Sie als Gegenmaßnahme die Ausnahmebehandlung hinzu, wenn das Kennwort leer ist. In einem solchen Fall ist es zweckmäßig, die Option `allow_nil: true``` zu verwenden. Selbst wenn es leer ist, wird es damit nicht bei der Validierung erfasst. Diese Option besteht die Existenzüberprüfung, aber beim Erstellen eines Objekts auf der Methodenseite "has_secure_password" Da die Validierung der Existenz funktioniert, wird beim Erstellen eines neuen Nulls abgestoßen, und wenn es beim Aktualisieren Null ist, wird das Kennwort nicht geändert. Die Operation kann realisiert werden. Durch Hinzufügen dieser Option `allow_nil: truewird außerdem die Validierung im Modell definierthas_secure_password```Es löst auch das Problem, dass dieselbe Fehlermeldung aufgrund einer doppelten Methodenüberprüfung angezeigt wird.

Übung
  1. Erfolg haben image.png

  2. Stattdessen wird das Standard-Gravatar-Bild angezeigt. image.png

Genehmigung

Die Authentifizierung in einer Web-App identifiziert den Benutzer. Die Autorisierung dient zum Verwalten des Bereichs von Vorgängen, die vom Benutzer ausgeführt werden können. Die bisher implementierten Aktualisierungs- und Bearbeitungsaktionen weisen erhebliche Mängel auf. Im aktuellen Status können alle Benutzer bearbeitet werden, unabhängig davon, welcher Benutzer angemeldet ist. Über den Link Einstellungen in der Navigationsleiste gelangen Sie zur Bearbeitungsseite des angemeldeten Benutzers Wenn Sie die Bearbeitungsaktion verschiedener Benutzer direkt in der URL angeben, können Sie darauf zugreifen und sie aktualisieren.

Das ist schlecht, also ändern Sie das Verhalten auf das richtige. Speziell Wenn Sie sich nicht angemeldet haben, leiten Sie zur Anmeldeseite weiter und zeigen Sie eine Nachricht an. Wenn Sie angemeldet sind, aber versuchen, auf einen anderen Benutzer zuzugreifen, leiten Sie an die Stamm-URL weiter.

Fordern Sie den Benutzer auf, sich anzumelden

Vor dem Bearbeiten wird die Aktualisierungsaktion mithilfe des Vorher-Filters auf dem Benutzer-Controller ausgeführt Stellen Sie sicher, dass Sie implementieren, um die Anmeldung zu erzwingen.

  before_action :logged_in_user, only:[:edit,update]
  .
  .
  .
    def logged_in_user
      unless logged_in?
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end

Auf diese Weise wird die Methode logged_in_user immer ausgeführt, bevor die Bearbeitungs- und Aktualisierungsaktionen ausgeführt werden. Wenn Sie nicht angemeldet sind, wird eine Flash-Meldung angezeigt, in der Sie aufgefordert werden, sich anzumelden. Leiten Sie zur Anmeldeseite weiter.

Wenn Sie zu diesem Zeitpunkt auf die Bearbeitungsansicht zugreifen, ohne sich anzumelden, werden Sie zur Anmeldeseite weitergeleitet. Der Test schlägt fehl, da er jetzt übersprungen wird.

Melden Sie sich in user_edit_test.rb an, bevor Sie auf die Bearbeitungsaktion zugreifen, damit der Test bestanden wird. Verwenden Sie die Methode log_in_as, da sie zum Testen definiert ist.

Der Test wird nun bestanden. Das Auskommentieren der Zeile before_action lehnt den Test jedoch nicht ab. Dies ist eine ernsthafte Sicherheitslücke und es ist schlecht, wenn es nicht getestet wird Ich werde es reparieren, damit es im Test fest abstößt.

  test "should redirect edit when not logged in" do
    get edit_user_path(@user)
    assert_not flash.empty?
    assert_redirected_to login_path
  end
  
  test "should redirect update when not logged in" do
    patch user_path(@user), params:{ user: {name: @user.name,  
                                            email: @user.email }}
    assert_not flash.empty?
    assert_redirected_to login_path
  end 

Durch Hinzufügen solcher Tests Aktualisieren Sie die Aktionen, um immer zu testen, ob log_in_user ausgeführt wird, bevor Sie die Bearbeitung ausführen Dadurch werden Sicherheitslücken in Tests geöffnet.

Übung
  1. Eine neue Seite oder Anmeldeaktion kann nicht ausgeführt werden und es tritt ein Fehler auf.
 FAIL["test_should_get_new", #<Minitest::Reporters::Suite:0x00007f1d1cf4dab8 @name="UsersControllerTest">, 0.06502773099964543]
 test_should_get_new#UsersControllerTest (0.07s)
        Expected response to be a <2XX: success>, but was a <302: Found> redirect to <http://www.example.com/login>
        Response body: <html><body>You are being <a href="http://www.example.com/login">redirected</a>.</body></html>
        test/controllers/users_controller_test.rb:10:in `block in <class:UsersControllerTest>'

 FAIL["test_invalid_signup_information", #<Minitest::Reporters::Suite:0x00007f1d1cff74c8 @name="UsersSignupTest">, 0.08553676799965615]
 test_invalid_signup_information#UsersSignupTest (0.09s)
        expecting <"users/new"> but rendering with <[]>
        test/integration/users_signup_test.rb:12:in `block in <class:UsersSignupTest>'

 FAIL["test_valid_signup_information", #<Minitest::Reporters::Suite:0x00007f1d1d0494d0 @name="UsersSignupTest">, 0.09624041300003228]
 test_valid_signup_information#UsersSignupTest (0.10s)
        "User.count" didn't change by 1.
        Expected: 2
          Actual: 1
        test/integration/users_signup_test.rb:20:in `block in <class:UsersSignupTest>'

  9/9: [================================================================] 100% Time: 00:00:01, Time: 00:00:01

Fordern Sie den richtigen Benutzer an

Selbst wenn Sie angemeldet sind, können Sie es als Nächstes selbst bearbeiten. Wir werden mit TDD fortfahren.

Fügen Sie zunächst einen zweiten Benutzer zum Fixture hinzu, um eine Situation zu erstellen, in der Sie sich als anderer Benutzer anmelden.

users.yml


archer: 
  name: Sterling Archer
  email: [email protected]
  password_digest: <%= User.digest('password') %>

Dann melden Sie sich im Test als @other_user an und Schreiben Sie einen Test, um @user zu aktualisieren.

  test "should redirect edit when logged in as wrong user" do
    log_in_as(@other_user)
    get edit_user_path(@user)
    assert flash.empty?
    assert_redirected_to root_path
  end
  
  test "should redirect update when logged in as wrong user" do
    log_in_as(@other_user)
    patch user_path(@user), params:{ user: { name: @user.name,
                                             email: @user.email}}
    assert flash.empty?
    assert_redirected_to root_path
  end

Dies ist ein Test, da die Flash-Nachricht nicht angezeigt wird und nur zur Stamm-URL übersprungen wird.

Ich schreibe einen Test und natürlich besteht er nicht Schreiben Sie den Code, um den Test zu bestehen.

Insbesondere wenn Sie eine `` `rect_user``` -Methode erstellen und vor dem Ausführen der Bearbeitung kein Benutzer vorhanden ist, aktualisieren Sie die Aktion Schreiben Sie den Prozess, um zur Stamm-URL zu springen.

users_controller.rb


  before_action :correct_user, only:[:edit,:update]
    


  private
    def correct_user
      @user = User.find(params[:id])
      redirect_to root_url unless @user == current_user
    end

Der Test wird nun bestanden.

Definieren Sie abschließend die Methode `current_user?` Und integrieren Sie sie in die zuvor definierte Methode `` `rect_user```.

    def correct_user
      @user = User.find(params[:id])
      redirect_to root_url unless current_user?(@user)
    end
  def current_user?(user)
    user && user == current_user
  end
Übung
  1. Wenn Sie die Aktualisierungsaktion nicht direkt mit dem Befehl curl usw. schützen, ohne die Bearbeitungsaktion (Bearbeitungsseite) durchlaufen zu haben Wenn Sie einen Wert senden, können Sie ihn aktualisieren.

  2. Die Bearbeitungsaktion ist einfacher zu testen. (Melden Sie sich tatsächlich an und zeigen Sie den Bearbeitungspfad eines anderen Benutzers an.)

Freundliche Weiterleitung

Dies macht diese Update-Funktion auch nützlich. Speziell logged_in_userWenn die Methode den Zugriff auf die Bearbeitungsseite eines nicht angemeldeten Benutzers zurückweist und zur Anmeldeseite springt Wenn Sie sich so anmelden, wie es ist, werden Sie zur Seite mit den Benutzerdetails (Anzeigen) übersprungen, ohne Fragen zu stellen. Es ist etwas unpraktisch, die Show-Seite zu sehen, wenn ich mich anmelde, um auf die Bearbeitungsseite zuzugreifen. Verbessern Sie dies, damit Sie beim Anmelden zur Bearbeitungsseite weitergeleitet werden (freundliche Weiterleitung).

Da der Test auf diese Weise implementiert werden kann Aktivieren Sie diese Option, um auf die Bearbeitungsseite zuzugreifen, ohne sich anzumelden, und leiten Sie sie nach der Anmeldung zur Bearbeitungsseite weiter.

test "successful edit with friendly forwarding" do
    get edit_user_path(@user)
    log_in_as(@user)
    assert_redirected_to edit_user_url(@user)
    name = "foo"
    email = "[email protected]"
    patch user_path(@user) , params:{user:{name: name,
                                           email: email,
                                           password: "",
                                           password_confirmation: ""}}
    
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal name, @user.name
    assert_equal email, @user.email
  end

Nachdem ich einen Test geschrieben habe, der an dieser Stelle fehlschlägt, schreibe ich den Code so, dass dieser Test erfolgreich ist. Schreiben Sie einen Prozess, um die Seite zum Zeitpunkt der Anforderung zu speichern und beim Anmelden darauf umzuleiten.

Definieren Sie eine Methode in session_helper.

sessions_helper.rb


  def redirect_back_or(default)
    redirect_to(session[:forwarding_url] || default)
    session.delete(:forwarding_url)
  end
  
  def store_location
    session[:forwarding_url] = request.original_url if request.get?
  end

store_locationDann Ich schreibe einen Prozess, um die URL des Anforderungsziels in einer temporären Sitzung zu speichern. Zu diesem Zeitpunkt muss ich nur die GET-Anforderung speichern

In dem unwahrscheinlichen Fall, dass Sie sich anmelden, um auf die Formularseite zuzugreifen und die absichtlich gespeicherten Cookies für Anmeldeinformationen zu löschen Wenn ich den Inhalt des Formulars abschicke, werden URLs wie Post und Patch gespeichert. Wenn Sie in diesem Zustand die Methode `` `redirect_back_or``` verwenden, wird eine GET-Anforderung an die URL gesendet, die Post, Patch usw. durch Weiterleitung erwartet. Es wird gesendet und es besteht eine hohe Wahrscheinlichkeit, dass ein Fehler auftritt. Sie können diese Risiken vermeiden, indem Sie sich auf GET-Anforderungen konzentrieren.

logged_in_userZur Methodestore_locationSetzen Sie die Methode, speichern Sie die Anforderungsziel-URL, Indem Sie die `redirect_back_or-Methode `in die Erstellungsaktion von session_controller einfügen Wenn beim Anmelden eine URL in der Sitzung gespeichert ist, leiten Sie diese weiter.

sessions_controller.rb


  def create
    @user = User.find_by(email: params[:session][:email].downcase)
    if @user&.authenticate(params[:session][:password])
      log_in(@user)
      params[:session][:remember_me] == '1' ? remember(@user) : forget(@user)
      redirect_back_or @user
    else
      flash.now[:danger] = "Invalid email/password combination"
      render 'new'
    end
  end

users_controller.rb


    def logged_in_user
      unless logged_in?
        store_location
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end

Übrigens, es sei denn, es erfolgt eine Rückgabe oder ein direkter Aufruf der letzten Zeile der Methode Die Umleitung erfolgt am Ende der Methode.

Der Test besteht mit den oben genannten Inhalten.

Übung
  1. Stellen Sie sicher, dass die gespeicherte URL verschwindet, wenn Sie sich anmelden und zur Bearbeitungsseite umleiten.

user_edit_test.rb


  test "successful edit with friendly forwarding" do
    get edit_user_path(@user)
    log_in_as(@user)
    assert_nil session[:forwarding_url] #Hier hinzufügen
    assert_redirected_to edit_user_url(@user)
    name = "foo"
    email = "[email protected]"
    patch user_path(@user) , params:{user:{name: name,
                                           email: email,
                                           password: "",
                                           password_confirmation: ""}}
    
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal name, @user.name
    assert_equal email, @user.email
  end
(byebug) session[:forwarding_url]
"https://12b7e3b6aec94b45960b81560e233372.vfs.cloud9.us-east-2.amazonaws.com/users/1/edit"
(byebug) request.get?
true

Schließlich

Ich habe am Ende des Kapitels immer mehr gemacht Ich werde es vorerst zusammenfassen.

rails t
git add -A
git commit -m "Finish user edit, update, index and destroy actions"
git co master
git merge updating-users
git push
rails t 
git push heroku
heroku pg:reset DATABASE
heroku run rails db:migrate
heroku run rails db:seed

Die Produktions-DB lautet `pg: reset DATABASE `. Außerdem der Anwendungsname, der die Datenbank zurücksetzt, um Fehler zu vermeiden Sie werden aufgefordert, es einzugeben. Geben Sie es ein und setzen Sie es zurück Oder mit der Option --confirm

reset DATABASE -c App-Name


 Du kannst es schaffen.

 Danach migrieren und Proben auf Heroku hinzufügen und fertig.


 [Zum vorherigen Kapitel](https://qiita.com/take_webengineer/items/48bb1a43ffac4290959f)

 [Zum nächsten Kapitel]()


Recommended Posts

Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 10
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 7
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 4
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 9
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 6
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 5
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 2
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 3
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 8
Rails Tutorial (4. Ausgabe) Memo Kapitel 6
Rails Tutorial Kapitel 3 Lernen
Rails Tutorial Kapitel 4 Lernen
Rails Tutorial Kapitel 1 Lernen
Rails Tutorial Kapitel 2 Lernen
Rails Tutorial 4. Ausgabe: Kapitel 1 Von Null bis Bereitstellung
Schienen-Tutorial Kapitel 6
Schienen-Tutorial Kapitel 1
Schienen-Tutorial Kapitel 7
Schienen-Tutorial Kapitel 5
Schienen-Tutorial Kapitel 10
Schienen-Tutorial Kapitel 9
Schienen-Tutorial Kapitel 8
Rails Tutorial Kapitel 0: Vorbereitende Grundkenntnisse 5
[Rails] Lernen mit Rails Tutorial
Rails Tutorial Memorandum (Kapitel 3, 3.1)
[Rails Tutorial Kapitel 4] Ruby mit Rails-Geschmack
[Rails Tutorial Kapitel 5] Erstellen Sie ein Layout
Tutorial zum Kauen der Schienen [Kapitel 2 Spielzeuganwendung]
Schienen Tutry
Schienen Tutorial
Schienen Tutry
Deshalb habe ich dieses Mal die Methode "Verknüpfen des Inhalts des Verzeichnisses" übernommen. Ich denke, es wird je nach Zeit und Fall richtig verwendet. Tutorial zu Linux, ln, Linux-Befehlsschienen
Schienen Tutry
Schienen Tutorial
Schienen Tutorial
Nur Zusammenfassung zum Einrichten des Rails-Tutorials
Rails Tutorial Test
Rails Tutorial Memorandum 1
Rails Tutorial Kapitel 1 Von Null bis Bereitstellung [Try]
Rails Lerntag 3
Rails Tutorial Memorandum 2
Rails Lerntag 4