[RUBY] Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 6

Ü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?

Erstellen Sie ein Benutzermodell. In den folgenden Kapiteln werden wir weiterhin Benutzermodelle erstellen.

Benutzermodell

Benutzerdaten, die mit ziemlicher Sicherheit in Web-Apps vorhanden sind ID, Name, E-Mail-Adresse, Passwort, Adresse usw. Erstellen Sie aus der Datenstruktur der Datenbank, die beim Erstellen dieser Daten gespeichert wird. Diese Datenstruktur heißt Modell Die Bibliothek, die mit der Datenbank interagiert, heißt ActiveRecord in Rails. Mit ActiveRecord müssen Sie normalerweise nicht über die für den Betrieb der Datenbank erforderliche SQL informiert sein. Rails verwendet auch eine Funktion namens Migration, um SQL von der Datenbankerstellung zu trennen. Dank dessen kann nur Rails die Datenbank betreiben.

Datenbankmigration

Lassen Sie uns sofort ein Benutzermodell erstellen. Woran ich mich hier erinnern möchte Controller-Name: Mehrere Formulare → Benutzer, Mikroposts usw. Modellname: Einzelformular → Benutzer, Mikropost usw. Nennen Sie es so.

rails g model User name:string email:string


 Dieser Befehl erstellt ein Benutzermodell mit dem Namen der Zeichenspalten und der E-Mail-Adresse.
 Übrigens, wenn Sie mit dem Befehl generate ein Modell erstellen
 Dies ist sehr praktisch, da gleichzeitig Migrationsdateien, Testdateien und Fixtures generiert werden.

 Dieses Mal habe ich zwei Attribute definiert, Name und E-Mail, aber Rails fügt automatisch drei Spalten hinzu.
 Hier ist es

 |users||
 |:--|:--|
 |id|integer|
 |name|string|
 |email|string|
 |created_at|datetime|
 |updated_at|datetime|

 Aus Rails Tutorial 6. Ausgabe
https://railstutorial.jp/chapters/modeling_users?version=6.0#fig-user_model_initial

 id ist ein eindeutiger Wert, mit dem der Datensatz eindeutig identifiziert werden kann
 created_at ist der Zeitpunkt, zu dem der Datensatz erstellt wurde
 update_at gibt die Zeit an, zu der die Daten des Datensatzes aktualisiert wurden.


 Da die Migrationsdatei gleichzeitig mit dem Modell mit dem Befehl generate früher generiert wurde
 Ich werde sofort migrieren.

#### **`migrate`**
```rails db


##### Übung
 1. Vergleichen Sie Schema und Migration

create_table "users", force: :cascade do |t| t.string "name" t.string "email" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end

create_table :users do |t|
  t.string :name
  t.string :email

  t.timestamps
end

 Weder hat eine Zeile, die die ID definiert, aber Zeitstempel sind im Schema fein definiert.
 Das Gefühl ist, dass das Ausführungsergebnis der durch Migration entworfenen Datenbank ein Schema ist.

 2. Mit `` `Rails db: Rollback```

== 20200608105854 CreateUsers: reverting ====================================== -- drop_table(:users) -> 0.0047s == 20200608105854 CreateUsers: reverted (0.0125s) =============================

 Die Tabelle wurde mit dem Befehl drop_table gelöscht.

 3. `` `Rails db: migrate``` erstellt die Tabelle wie zuvor. (Ergebnisse weggelassen)

#### Modelldatei
 Lassen Sie uns die Klassenvererbungsstruktur des Benutzermodells als Überprüfung überprüfen.

$ rails c Running via Spring preloader in process 7640 Loading development environment (Rails 6.0.3)

User.superclass => ApplicationRecord(abstract)

User.superclass.superclass => ActiveRecord::Base


User < ApplicationRecord < ActiveRecord::Base
 Mit dieser Struktur erbt das Benutzermodell alle Funktionen von ActiveRecord :: Base.
 Daher kann die Benutzerdatenbank auch mit ActiveRecord-Methoden betrieben werden.

##### Übung
 1. Es ist fast das gleiche wie in ↑.

user = User.new (0.4ms) SELECT sqlite_version(*) => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>

user.class.superclass => ApplicationRecord(abstract)


 2. Dies ist genau das Gleiche wie in ↑. Lassen Sie es also weg.

#### Erstellen Sie ein Benutzerobjekt
 Versuchen wir, ein Benutzerobjekt zu erstellen.
 Wenn Sie die Datenbank nicht ändern möchten (wenn Sie dies versuchen), verwenden Sie den Sandbox-Modus.
```rails console --sandbox```Oder```rails c -s```
 In diesem Modus werden alle Änderungen rückgängig gemacht (abgebrochen), wenn die Konsole geschlossen wird. Dies ist praktisch, wenn Sie es versuchen.

 Die wichtigsten Punkte hier sind zusammengefasst.
 -Benutzerobjekt kann mit User.new erstellt werden.

 -Das von User.new erstellte Benutzerobjekt kann von User.save gespeichert werden. (Wenn Sie nicht speichern, wird es nicht in der Datenbank gespeichert.)

 - Sie können anhand des von user.valid zurückgegebenen logischen Werts feststellen, ob der erstellte Benutzerobjektbenutzer gültig ist.

 -Created_at und updated_at sind null, wenn das Benutzerobjekt mit der neuen Methode erstellt wird, aber die Zeit, zu der es gespeichert wird
 Wird ersetzt.

 -Wenn Sie User.create verwenden, können Sie Objekte gleichzeitig erstellen und speichern.


##### Übung
 1. Beachten Sie, dass wenn Sie nichts in Name und E-Mail eingeben, es null und NilClass ist.

user.email.class => String

user.name.class => String


2.ActiveSupport::TimeWithZone

user.created_at.class => ActiveSupport::TimeWithZone

user.updated_at.class => ActiveSupport::TimeWithZone


#### Suche nach Benutzerobjekten
 Fassen Sie die Punkte zusammen.
 - Geben Sie den entsprechenden Benutzer in User.find (Benutzer-ID) zurück.

 - Gibt den entsprechenden Benutzer in User.find_by zurück (Attribut: Suchwert).

 · User.first gibt den ersten Benutzer in der Datenbank zurück

 -Alle in der Datenbank in User.all registrierten Datensätze haben ein Array-ähnliches Format.
 Rückgabe als (ActiveRecord_Relation).

##### Übung
 1. find_by_name hat dieselbe Operation, verwendet jedoch die Übergabe eines Hashs an das Argument von basic find_by.

user = User.find_by(name: "take") User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "take"], ["LIMIT", 1]] => #<User id: 2, name: "take", email: "[email protected]", created_at: "2020-06-08 12:38:02", updated_at: "2020-06-08 12:38:02">

user = User.find_by_name("take") User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "take"], ["LIMIT", 1]] => #<User id: 2, name: "take", email: "[email protected]", created_at: "2020-06-08 12:38:02", updated_at: "2020-06-08 12:38:02">

user = User.find_by_email("[email protected]")


2.

user = User.all User Load (0.2ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]] => #<ActiveRecord::Relation [#<User id: 1, name: nil, email: nil, created_at: "2020-06-08 12:32:30", updated_at: "2020-06-08 12:32:30">, #<User id: 2, name: "take", email: "[email protected]", created_at: "2020-06-08 12:38:02", updated_at: "2020-06-08 12:38:02">]>

user.class => User::ActiveRecord_Relation


 3. Ich möchte die Anzahl der Elemente (Anzahl) des Benutzers wissen → Es scheint nach Länge gezählt zu werden. → Sie können zählen, wenn Sie sie mit einer Methodenkette verbinden.
 Es wird als Ententypisierung bezeichnet, bei der Sie verstehen, wie Sie mit einer solchen Klasse umgehen, die Sie nicht im Detail kennen.

User.all.length User Load (0.2ms) SELECT "users".* FROM "users" => 2


#### Benutzerobjekt aktualisieren
 Es gibt zwei Möglichkeiten, den Inhalt eines Benutzerobjekts zu aktualisieren
 ・ Direkt ersetzen und speichern

user.name = "takemo" => "takemo"

user.save

 ・ Sofortiges Update mit Update-Methode

user.update(name: "take",email: "[email protected]")



 Wenn Sie nur ein Attribut aktualisieren, übergeben Sie den Attributnamen und den Wert anstelle des Hashs wie `` `update_attribute (: name," take ")` `.
 Um mehr als ein Attribut zu aktualisieren, übergeben Sie einen Hash wie `` `update (Name:" take ", E-Mail:" [email protected] ")` ``.

 Übrigens aktualisieren beide ein Attribut wie `` `update_attribute (: name," take ")` `` und `` `update (name:" take ")` ``
 Das Schreiben ohne Verwendung eines Hash als Argument (das erstere) hat auch den Effekt, dass eine "Überprüfung" der Daten vermieden wird, die von nun an gelernt werden **. ** **.

##### Übung
1.

user.name = "Saori Yoshida" => "Saori Yoshida"

user.save (0.1ms) SAVEPOINT active_record_1 User Update (0.1ms) UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ? [["name", "Saori Yoshida"], ["updated_at", "2020-06-08 13:50:14.777986"], ["id", 2]] (0.1ms) RELEASE SAVEPOINT active_record_1 => true

2.

user.update_attribute(:email,"[email protected]") (0.1ms) SAVEPOINT active_record_1 User Update (0.1ms) UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ? [["email", "[email protected]"], ["updated_at", "2020-06-08 13:56:20.532390"], ["id", 2]] (0.1ms) RELEASE SAVEPOINT active_record_1 => true

3.

user.update_attribute(:created_at,1.year.ago) (0.1ms) SAVEPOINT active_record_1 User Update (0.2ms) UPDATE "users" SET "created_at" = ?, "updated_at" = ? WHERE "users"."id" = ? [["created_at", "2019-06-08 13:57:32.050811"], ["updated_at", "2020-06-08 13:57:32.051252"], ["id", 2]] (0.1ms) RELEASE SAVEPOINT active_record_1 => true


### Überprüfen Sie den Benutzer
 Das Wort "Verifikation" wurde in den vorherigen Übungen mehrmals erwähnt.
 Es ist ein Datenlimit. Ein unbenannter Benutzer, eine fehlerhafte E-Mail-Adresse oder ein zu kurzes Kennwort
 Es darf nicht in der Datenbank registriert sein.
 Die Validierung verhindert dies.

#### Überprüfen Sie die Wirksamkeit
 Dieser Teil wird mit der testgetriebenen Entwicklung fortfahren
 Der erste Benutzermodelltest sieht so aus

require 'test_helper'

class UserTest < ActiveSupport::TestCase def setup @user = User.new(name: "Example User", email: "[email protected]") end

test "should be valid" do assert @user.valid? end end

 Hier ist die Setup-Methode, die vor jedem Test ausgeführt wird (derzeit nur eine).
 Definieren Sie einen Testbenutzer in der Variablen @user und

 Das sollten gültige Testtests sein, bei denen @user gültige Daten sind.

 Zu diesem Zeitpunkt wurde keine Validierung hinzugefügt und alle Daten sind gültig, sodass der Test definitiv bestanden wird.


#### **`models`**
```rails test

 Führen Sie nur die Tests aus, die sich auf das Modell in beziehen
 Es wird jedoch automatisch von Guard getestet und alle Tests werden auch bei manueller Ausführung ausgeführt.
 Ich habe es nie benutzt ...
 Es kann verwendet werden, wenn der Test selbst zunimmt und schwer wird.

##### Übung
1.

new_user = User.new => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>

new_user.valid? => true


2.

user.valid? => true


 Es ist offensichtlich, aber es wäre eine Art von Daten, da keine Validierung aktiviert ist.

#### Überprüfen Sie die Existenz
 Versuchen Sie, die einfachste und grundlegendste Validierung hinzuzufügen, Presense
 Durch Hinzufügen kann es nur aktiviert werden, wenn das Element vorhanden ist.

 Schreiben wir zuerst den Test.

test "name should be present" do @user.name = " " assert_not @user.valid? end

 Fügen Sie in diesem diesmal hinzugefügten Test ein Leerzeichen (nicht vorhanden) in das Namensattribut ein
 @ user.valid? Mit assert_not (wird übergeben, wenn das Argument falsch ist)
 Besteht den Test, wenn der Benutzer nicht gültig ist.
 Mit anderen Worten
 Setzen Sie ein Leerzeichen und testen Sie, ob der Benutzer ungültig ist, wenn der Name nicht vorhanden ist.

 Weil der Test zu diesem Zeitpunkt fehlschlägt
 Ich habe beschlossen, die Validierung hinzuzufügen und den Test zu bestehen.

class User < ApplicationRecord validates :name, presence: true end

 Ich denke, dass es hier ziemlich viele Leute gibt, die mit dem Schreiben beginnen.
 Wenn Sie diese Zeile schreiben, ohne sie wegzulassen

#### **`validates(:name,{presence: true})`**

Übergabe: Name als erstes Argument und Hash als zweites Argument (optional) an die validates-Methode. Rails bietet verschiedene Abkürzungen für Effizienz. Hier kann das () der Methode weggelassen werden, der letzte Hash des Arguments der Methode kann {} weglassen, Es werden zwei Abkürzungen verwendet. Da solche Abkürzungen auch in Zukunft selbstverständlich sind Ich werde so viel wie möglich erklären, aber es ist gut, sich jetzt daran zu gewöhnen.

Ich habe die Validierung hinzugefügt Ungültig, wenn der Name nicht existiert.

Überprüfen Sie, ob die Validierung auf der Konsole funktioniert.

>> user = User.new(name: "",email:"[email protected]")
   (0.1ms)  begin transaction
=> #<User id: nil, name: "", email: "[email protected]", created_at: nil, updated_at: nil>
>> user.valid?
=> false

Im deaktivierten Zustand kann es übrigens nicht in der Datenbank gespeichert werden.

>> user.save
=> false

Ein Fehler auf diese Weise erzeugt ein Fehlerobjekt und speichert die Fehlermeldung.

>> user.errors.full_messages
=> ["Name can't be blank"]

Wenn ich die Konsole verlasse und den Test ausführe, besteht der Test. Schreiben Sie einen Test für das E-Mail-Attribut und fügen Sie dann eine Validierung hinzu. (Probefahrt Entwicklung)

Testen der Existenz von E-Mails

  test "email should be present" do
    @user.email = " "
    assert_not @user.valid?
  end

Der Test schlägt hier fehl. E-Mail-Validierung hinzufügen

validates :email, presence: true



 Der Test besteht.

##### Übung
 1. Ich bin festgefahren, um die Existenz von Name und E-Mail zu überprüfen

u = User.new (0.1ms) begin transaction => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>

u.valid? => false

u.errors.full_messages => ["Name can't be blank", "Email can't be blank"]

 2. Da Nachrichten im Hash-Format vorliegen, können Sie sie abrufen, indem Sie [: email] angeben.

u.errors.messages => {:name=>["can't be blank"], :email=>["can't be blank"]}

u.errors.messages[:email] => ["can't be blank"]

#### Überprüfen Sie die Länge
 Derzeit ist der Name auf 50 Zeichen begrenzt, was einer angemessenen Anzahl von Zeichen entspricht.
 E-Mail-Adressen sind ebenfalls auf 255 Zeichen begrenzt. Dies ist die Standardzeichenbeschränkung.
 Schreiben Sie einen Test, bevor Sie eine Validierung hinzufügen.

test "name should not be long" do @user.name = "a" * 51 assert_not @user.valid? end

test "email should not be too long " do @user.email = "a" * 244 + "@example.com" assert_not @user.valid? end

 Ich habe viel investiert, um die Anzahl der Charaktere zu verdienen.
 Der Test besteht zu diesem Zeitpunkt noch nicht.

validates :name, presence: true, length:{maximum: 50} validates :email, presence: true, length:{maximum: 255}

 Dadurch wird die Anzahl der Zeichen überprüft und der Test bestanden.

##### Übung
1.

user = User.new(name:"a"*51,email:"a"*256) (0.1ms) begin transaction => #<User id: nil, name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...", email: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...", created_at: nil, updated_at: nil>

user.valid? => false


 2. Ich werde wütend, wenn es zu lang ist.

user.errors.messages => {:name=>["is too long (maximum is 50 characters)"], :email=>["is too long (maximum is 255 characters)"]}


##### Überprüfen Sie das Format
 Wenn Sie beim Erstellen eines neuen Kontos geeignete Zeichen in die E-Mail-Adresse eingeben, was häufig auf verschiedenen Websites angezeigt wird
 Ich werde oft wütend, wenn ich sage "Bitte geben Sie die richtige E-Mail-Adresse ein".
 Auf diese Weise prüfen wir zusätzlich zur Anzahl der Zeichen, ob das angegebene Format als E-Mail-Adresse erfüllt ist.

 Mit% w [] können Sie ganz einfach ein Array von Zeichenfolgen erstellen. Verwenden Sie diese Option, um eine ungültige E-Mail-Adressliste zu erstellen.

 Ein Test, um sicherzustellen, dass eine gültige E-Mail-Adresse nicht in der Validierung erfasst wird

test "email validation should accept valid address" do valid_addresses = %w[[email protected] [email protected] [email protected]] valid_addresses.each do |valid_address| @user.email = valid_address assert @user.valid? , "#{valid_address.inspect} should be valid" end end

 Mit dem zweiten Argument wird eine Fehlermeldung hinzugefügt, damit Sie sehen können, bei welcher E-Mail-Adresse der Test fehlgeschlagen ist.

 Als Nächstes wird ein Test durchgeführt, um sicherzustellen, dass ungültige E-Mail-Adressen fest in der Validierung erfasst sind

test "email validation should reject invalid address" do invalid_addresses = %w[user@example,com user_at_foo.org [email protected]@bar_baz.com foo@bar+baz.com] invalid_addresses.each do |invalid_address| @user.email = invalid_address assert_not @user.valid?, "#{invalid_address.inspect} should be invalid" end end


 Der Test besteht zu diesem Zeitpunkt noch nicht.
 Um den Test zu bestehen
 Validierung der E-Mail-Adresse hinzufügen.
 Sie müssen einen kanonischen Ausdruck schreiben, um das Format Ihrer E-Mail-Adresse zu überprüfen.
 Es gab eine Seite, die sehr einfach zu verstehen war, deshalb werde ich sie vorstellen.
https://murashun.jp/blog/20190215-01.html
 Natürlich ist auch das im Tutorial vorgestellte Rubular nützlich.

 Definieren Sie den regulären Ausdruck von E-Mail. In Ruby beginnen Konstanten mit einem Großbuchstaben.


#### **`user.rb`**
```rb

class User < ApplicationRecord
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :name, presence: true, length:{maximum: 50}
  validates :email, presence: true, length:{maximum: 255},
                    format: {with: VALID_EMAIL_REGEX}
                    
end

Ergänzung, da das Tutorial keine Erklärung enthielt. Der Teil [\ w + \ -.] Stellt alphanumerische Zeichen, Unterstriche, Pluszeichen, Bindestriche und Punkte dar. \ w entspricht alphanumerischen Zeichen und Unterstrich + -. Entspricht jedem, aber ich glaube, dass es ein zusätzliches \ gibt Dies ist der Effekt, wenn Sie dem Zeichen unmittelbar danach entkommen, und der Bindestrich unmittelbar danach hat in [] eine besondere Bedeutung. Es bewirkt die Angabe eines Bereichs [a-z](a bis z). Also zu entkommen und als Original anzuzeigen- Da es mit \ maskiert wird, wird es zu einem solchen Ausdruck.

Zu diesem Zeitpunkt besteht der Test.

Dieser reguläre Ausdruck enthält keine Reihe von Punkten wie sample @ gmail..com, daher werde ich ihn in der nächsten Übung korrigieren.

Übung

1.image.png

Passen Sie das richtige so an.

  1. Ich möchte eine Adresse wie foo @ bar..com abstoßen. Wenn Sie jedoch bis zu einem Punkt angeben, wird auch eine Adresse wie @ softbank.ne.jp abgelehnt. Also dieser Ausdruck

/\A[\w+\-.]+@[a-z\d\-.]+(\.[a-z\d\-.]+)*\.[a-z]+\z/i


 Dies ist `` `(\. [A-z \ d \ -.] +)` `` Und fügt ein weiteres Muster mit .〇〇〇 hinzu.

 Ungefähr das Gleiche wie 3.1
 Kürzung

#### Überprüfen Sie die Eindeutigkeit
 Die E-Mail-Adresse wird als Benutzername verwendet (z. B. beim Anmelden) und darf nicht zwischen Benutzern dupliziert werden.
 Hier wird eine eindeutige Validierung hinzugefügt.

 Mit User.new tritt keine Duplizierung auf, selbst wenn Sie die Datenbank nur durch Erstellen eines Objekts im Speicher abfragen.
 Mit anderen Worten, legen Sie Daten A in die Datenbank und testen Sie genau dieselben Daten B.

test "email address should be unique" do duplicate_user = @user.dup @user.save assert_not duplicate_user.valid? end

 Hier beheben
 E-Mail-Adressen unterscheiden normalerweise nicht zwischen Groß- und Kleinschreibung
 [email protected] und [email protected] werden gleich behandelt.
 Um dies gleichzeitig zu testen

test "email address should be unique" do duplicate_user = @user.dup duplicate_user.email.upcase! @user.save assert_not duplicate_user.valid? end

 Upcase die kopierten Adressen und vergleichen.
 Geben Sie zur Validierung in der Eindeutigkeitsoption einfach case_sensitive: false an.
 Die Bestätigung ist, dass die E-Mail-Adresse eindeutig sein muss, jedoch nicht zwischen Groß- und Kleinschreibung unterscheiden muss (beide sind gleich).


 Aber es gibt immer noch Mängel.
 Da die von uns hinzugefügte Validierung bereits beim Erstellen der Daten überprüft wird, bevor sie in der Datenbank registriert werden.
 In dem unwahrscheinlichen Fall, dass Sie die Überprüfung bestehen, wenn viel Verkehr und viel Verkehr herrscht, wenn Sie nacheinander Registrierungsanfragen senden
 Es wird so wie es ist in der Datenbank registriert.
 Um dies zu verhindern, können Sie erzwingen, dass es nicht nur beim Erstellen von Daten, sondern auch beim Registrieren von Daten eindeutig ist.

 Dies wird erreicht, indem der E-Mail-Spalte der Datenbank ein Index hinzugefügt und der Index als eindeutig erzwungen wird.
 * Ein Index ähnelt einem Datenbankindex. Durch Hinzufügen wird die Suchgeschwindigkeit der Daten verbessert.
 Ich werde hier nicht ins Detail gehen, aber beachten Sie, dass dies nicht bedeutet, dass Sie allen Daten einen Index hinzufügen sollten.

 Erstellen Sie eine Migrationsdatei, um einen Index hinzuzufügen
```$ rails g migration add_index_to_users_email```

 Während das Migrieren und Hinzufügen eines Index die Eindeutigkeit des Datenbank-E-Mail-Index erzwang
 Da das E-Mail-Attribut des Geräts, bei dem es sich um die Beispieldaten der Test-DB handelt, abgedeckt ist, wird ein Fehler ausgegeben.
 Dieses Gerät wird derzeit ebenfalls nicht verwendet. Löschen Sie daher den Inhalt
 Bisher wurde der Test bestanden, obwohl der Fixture-Wert vor der Registrierung in der Datenbank falsch war.
 Weil es ein Test zur Datenüberprüfung war (Fixture sind Daten, die im Voraus in der Test-DB registriert wurden)


 Das reicht aber noch nicht aus.
 Abhängig von der Datenbank kann der Index zwischen Groß- und Kleinschreibung unterscheiden oder nicht.
 Bei der Validierung des Benutzermodells kann die Eindeutigkeit {case_sensitive: false} verwendet werden.
 In einem solchen Fall wird das Verfahren zum Konvertieren aller Daten in Kleinbuchstaben vor der Registrierung in der Datenbank angewendet.

 Verwenden Sie die before_save-Methode von ActiveRecord, um anzugeben, dass alle Daten vor dem Speichern in Kleinbuchstaben konvertiert werden sollen.

#### **`  before_save { self.email.downcase! }`**

Dies ruft beim Speichern einen Rückruf auf und alle E-Mails werden in Kleinbuchstaben konvertiert. Daher `Eindeutigkeit: {case_sensitive: false}`

Es ist in Ordnung, es wieder auf true zu setzen


 Dies ist kein Problem, da es beim Speichern immer niedriger gemacht wird.


#### **`Wenn der Wert auf true zurückgesetzt wird, schlägt der Test fehl.`**
```uniqueness

 Die Validierung ist zurückgekehrt, um den Fall als anders zu behandeln.
 Daher stellt der Test auch den Teil wieder her, der in Großbuchstaben konvertiert wurde.

test "email address should be unique" do duplicate_user = @user.dup @user.save assert_not duplicate_user.valid? end


##### Übung
 1. Geben Sie vorerst nur das Ergebnis an, wenn Sie es auskommentiert haben.

FAIL["test_email_address_should_be_saved_as_lower-case", #<Minitest::Reporters::Suite:0x00007f75a0e7b310 @name="UserTest">, 0.06644777600013185] test_email_address_should_be_saved_as_lower-case#UserTest (0.07s) Expected: "[email protected]" Actual: "[email protected]" test/models/user_test.rb:58:in `block in class:UserTest'

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

Finished in 0.07422s 9 tests, 15 assertions, 1 failures, 0 errors, 0 skips


 Es ist leicht zu verstehen, da es Fehler in Form von erwarteten und tatsächlichen Werten gibt.
 Da der Rückruf durch Kommentieren aufgerufen wird und alle in Kleinbuchstaben umgewandelt und dann gespeichert werden.
 Der Test besteht ebenfalls.

 2. Wird weggelassen, weil es ursprünglich in `` `email.downcase!` `` Geschrieben wurde.
 Um es zu erklären, fügt hinzu! Macht es zu einer "destruktiven Methode". In diesem Fall wird die E-Mail-Adresse verkleinert und das Ergebnis "überschrieben".


### Fügen Sie ein sicheres Passwort hinzu
 Implementieren Sie das Benutzerkennwort.
 Anstatt nur das Passwort in der Datenbank zu registrieren, registrieren Sie die Hash-Version mit der Hash-Funktion.
 Erforderlich, da das Risiko erheblich geringer ist als bei der Registrierung.

#### Hashed Passwort
 Es gibt eine bequeme Methode zum Implementieren von Passwörtern
```has_secure_password```80% werden nur durch Hinzufügen beendet.
 Durch Aufrufen dieser Methode im Modell
 -Das Hash-Passwort kann im Attribut password_digest gespeichert werden. ""
 ・ Gleichzeitig mit den virtuellen Attributen Passwort und Passwortbestätigung werden verfügbar
 Es wird auch eine Validierung hinzugefügt, um festzustellen, ob die Existenz und die Werte dieser beiden Attribute übereinstimmen.
 -Die `` `authenticate``` Methode kann verwendet werden.

 Natürlich gibt es auch andere Vorbereitungen, password_digest ist offensichtlich, muss aber im Modell enthalten sein.
 Erstellen Sie daher eine Migrationsdatei zum Hinzufügen von password_digest.


#### **`string`**
```rails g migration add_password_digest_to_users password_digest


 Rails interpretiert die Änderung an der Benutzertabelle, indem die Migrationsdatei mit to_users beendet wird.
 Wenn Sie nach dem Dateinamen auch password_digest: string schreiben, wird der Benutzertabelle der Zeichenfolgentyp password_digest hinzugefügt.
 Es wird automatisch eine Migration erstellt. Sehr angenehm.

 Wie oben erwähnt, muss die Migrationsdatei nicht geändert werden. Migrieren Sie sie also so, wie sie ist.

 Darüber hinaus ist für das Passwort-Hashing bcrypt erforderlich, eine Hash-Funktion auf dem neuesten Stand der Technik.
 Fügen Sie bcrypt zu Ihrer Gemfile hinzu, um bcrypt zu verwenden.


#### **`gem 'bcrypt', '3.1.13'`**

Nach dem Hinzufügen klicken Sie auf Bundle.

Der Benutzer hat ein sicheres Passwort.

Nachdem wir has_secure_password verwenden können, fügen Sie dem Benutzermodell `` `has_secure_password``` hinzu. Die Überprüfung, ob das Vorhandensein und der Wert der virtuellen Attribute password und password_confirmation identisch sind, bleibt hängen. Übergeben Sie den Wert dieser beiden Attribute an das @ user-Attribut des Tests.

Übung
>> user1 = User.new(name:"takemo",email:"[email protected]")
=> #<User id: nil, name: "takemo", email: "[email protected]", created_at: nil, updated_at: nil, password_digest: nil>
>> user1.valid?
  User Exists? (0.1ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "[email protected]"], ["LIMIT", 1]]
=> false
  1. Ich bin in der Validierung der Existenz eines Passworts gefangen.
>> user1.errors.full_messages
=> ["Password can't be blank"]

Mindestanzahl von Zeichen im Passwort

Überprüfen Sie die Mindestanzahl von Zeichen (6 Zeichen) für das Kennwort. Schreiben Sie zuerst den Test. Schreiben Sie einen Test, um einen Fehler auszulösen, wenn das Kennwort leer oder weniger als 6 Zeichen lang ist.

  test "password should be present (nonblank)" do
    @user.password = @user.password_confirmation = " " * 6
    assert_not @user.valid?
  end
  
  test "password should have a minimum length" do
    @user.password = @user.password_confirmation = "a" * 5
    assert_not @user.valid?
  end

`` `@ User.password =" @ user.password_confirmation = "" * 6``` Verwendet mehrere Zuweisungen, um zwei Elementen gleichzeitig zuzuweisen.

Nachdem wir den Test geschrieben haben, implementieren wir die Validierung. Verwenden Sie die minimale Option, die das Gegenteil von maximal ist, da dies die minimale Anzahl von Zeichen ist.

validates :password, presence: true, length:{minimum: 6}



 Der Test besteht, wenn die Validierung hinzugefügt wird.

##### Übung
1.

user1 = User.new(name:"takemo",email:"[email protected]",password:"foo",password_confirmation:"foo") (0.1ms) begin transaction => #<User id: nil, name: "takemo", email: "[email protected]", created_at: nil, updated_at: nil, password_digest: [FILTERED]>

user1.valid? User Exists? (0.6ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]] => false

2.

user1.errors.messages => {:password=>["is too short (minimum is 6 characters)"]}


#### Benutzererstellung und -authentifizierung
 Erstellen Sie einen neuen Benutzer in der Entwicklungsumgebung, um die zukünftige Erstellung der Indexseite vorzubereiten.
 Die Benutzererstellungsfunktion aus dem Web wurde noch nicht implementiert. Fügen Sie sie daher über die Rails-Konsole hinzu.

User.create(name:"take",email:"[email protected]",password:"foobar",password_confirmation:"foobar") (0.4ms) SELECT sqlite_version(*) (0.1ms) begin transaction User Exists? (0.8ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]] User Create (3.3ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at", "password_digest") VALUES (?, ?, ?, ?, ?) [["name", "take"], ["email", "[email protected]"], ["created_at", "2020-06-10 12:51:23.959140"], ["updated_at", "2020-06-10 12:51:23.959140"], ["password_digest", "$2a12xkZDNGfs2Dnjzbm5XxfCfu.sB3I4ug4PFtTHukKdp0EF9YLLsE5Sm"]] (6.7ms) commit transaction => #<User id: 1, name: "take", email: "[email protected]", created_at: "2020-06-10 12:51:23", updated_at: "2020-06-10 12:51:23", password_digest: [FILTERED]>


 Wenn Sie in password_digest nachsehen, wird das gehashte Passwort gespeichert.

user.password_digest => "$2a12xkZDNGfs2Dnjzbm5XxfCfu.sB3I4ug4PFtTHukKdp0EF9YLLsE5Sm"


 Wie bereits erläutert, wird die Methode `` `authenticate``` durch die Methode` `` has_secure_password``` aktiviert.
 Ich werde es versuchen.

user.authenticate("foo!baka") => false


 Es wird false für das falsche Passwort zurückgegeben.

user.authenticate("foobar") => #<User id: 1, name: "take", email: "[email protected]", created_at: "2020-06-10 12:51:23", updated_at: "2020-06-10 12:51:23", password_digest: [FILTERED]>

 Gibt ein Benutzerobjekt mit dem richtigen Kennwort zurück. (wahr)
 Sie können es auch mit !! in einen logischen Wert konvertieren und zurückgeben → `` `!! user.authenticate (" foobar ")` `

##### Übung
1.

u = User.find_by(email:"[email protected]") (0.4ms) SELECT sqlite_version() User Load (0.2ms) SELECT "users". FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]] => #<User id: 1, name: "take", email: "[email protected]", created_at: "2020-06-10 12:51:23", updated_at: "2020-06-10 12:51:23", password_digest: [FILTERED]>

 2. Das Kennwort für das virtuelle Attribut ist leer, sodass es bei der Validierung hängen bleibt.
 Das zuvor eingegebene Kennwort wird gehasht und in der Datenbank als password_digest gespeichert. Sie müssen das Kennwort daher jedes Mal eingeben.

u.name = "taketake" => "taketake"

u.save (0.1ms) begin transaction User Exists? (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? AND "users"."id" != ? LIMIT ? [["email", "[email protected]"], ["id", 1], ["LIMIT", 1]] (0.1ms) rollback transaction => false


 3. Mit der Methode update_attribute können Sie die Validierung umgehen und den Wert direkt aktualisieren.

u.update_attribute(:name,"taketake") (0.1ms) begin transaction User Update (2.1ms) UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ? [["name", "taketake"], ["updated_at", "2020-06-10 13:09:09.579353"], ["id", 1]] (6.4ms) commit transaction => true


### Schließlich
 Übernehmen Sie die bisherigen Änderungen an Git
 Push and Deploy.
 Vergessen Sie nicht, die Datenbank der Produktionsumgebung zu migrieren.

 [Zum vorherigen Kapitel](https://qiita.com/take_webengineer/items/6949dc3131d4f34e27c0)

 [Zum nächsten Kapitel]()


Recommended Posts

Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 7
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
Rails 6.0-Routing-Zusammenfassung
Schienen lernen Tag 2
Kauen der Schienen Tutorial [Kapitel 3 Erstellen fast statischer Seiten]