Cet article approfondit ma compréhension en écrivant un article de commentaire du tutoriel Rails pour solidifier davantage mes connaissances Cela fait partie de mon étude. Dans de rares cas, il peut contenir un contenu ridicule ou incorrect. Notez s'il vous plaît. J'apprécierais que vous me disiez implicitement ...
La source Tutoriel Rails 6e édition
Créez un modèle utilisateur. Nous continuerons à créer des modèles utilisateur dans les chapitres suivants.
Données utilisateur qui existent presque certainement dans les applications Web ID, nom, adresse e-mail, mot de passe, adresse, etc ... Créez à partir de la structure de données de la base de données enregistrée lors de la création de ces données. Cette structure de données est appelée modèle La bibliothèque qui interagit avec la base de données est appelée ActiveRecord in Rails. Avec ActiveRecord, vous n'avez généralement pas besoin de connaître le SQL requis pour faire fonctionner la base de données. Rails utilise également une fonctionnalité appelée migration pour séparer SQL de la création de base de données. Grâce à cela, Rails seul peut faire fonctionner la base de données.
Créons un modèle utilisateur à la fois. Ce dont je veux me souvenir ici Nom du contrôleur: Formulaire multiple → Utilisateurs, micropostes, etc. Nom du modèle: Formulaire unique → Utilisateur, Micropost, etc. Nommez-le comme ça.
rails g model User name:string email:string
Cette commande crée un modèle utilisateur avec le nom des colonnes de caractères et l'adresse e-mail.
Au fait, si vous créez un modèle avec la commande generate
C'est très pratique car il génère également des fichiers de migration, des fichiers de test et des fixtures en même temps.
Cette fois, j'ai défini deux attributs, nom et email, mais Rails ajoute automatiquement trois colonnes.
Le voici
|users||
|:--|:--|
|id|integer|
|name|string|
|email|string|
|created_at|datetime|
|updated_at|datetime|
From Rails Tutorial 6e édition
https://railstutorial.jp/chapters/modeling_users?version=6.0#fig-user_model_initial
id est une valeur unique pour identifier de manière unique l'enregistrement tel qu'il est
created_at est l'heure à laquelle l'enregistrement a été créé
updated_at représente l'heure à laquelle les données de l'enregistrement ont été mises à jour.
Puisque le fichier de migration a été généré en même temps que le modèle avec la commande generate plus tôt
Je vais migrer immédiatement.
#### **`migrate`**
```rails db
##### Exercice
1. Comparez le schéma et la 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
Aucun des deux n'a de ligne définissant l'ID, mais les horodatages sont définis avec précision dans le schéma.
Le sentiment est que le résultat de l'exécution de la base de données conçue par migration est un schéma.
2. Avec `` `rails db: rollback```
== 20200608105854 CreateUsers: reverting ====================================== -- drop_table(:users) -> 0.0047s == 20200608105854 CreateUsers: reverted (0.0125s) =============================
La table a été supprimée avec la commande drop_table.
3. `` `` rails db: migrate``` créera la table comme avant. (Résultats omis)
#### fichier modèle
Vérifions la structure d'héritage de classe du modèle User à titre de révision.
$ 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
Avec cette structure, le modèle User hérite de toutes les fonctionnalités d'ActiveRecord :: Base.
Par conséquent, la base de données utilisateur peut également être exploitée à l'aide des méthodes ActiveRecord.
##### Exercice
1. C'est presque la même chose que ce que j'ai fait dans ↑.
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. C'est exactement la même chose que ce que vous faites dans ↑, alors omettez-le.
#### Créer un objet utilisateur
Essayons de créer un objet utilisateur.
Si vous ne voulez pas changer la base de données (en essayant comme ça), utilisez le mode sandbox.
```rails console --sandbox```Ou```rails c -s```
Ce mode annule (annule) toutes les modifications lorsque la console est fermée, ce qui est pratique lorsque vous essayez.
Les principaux points ici sont résumés.
-L'objet utilisateur peut être créé avec User.new.
-L'objet User créé par User.new peut être sauvegardé par User.save. (Si vous ne sauvegardez pas, il ne sera pas stocké dans la base de données)
-Vous pouvez dire si l'utilisateur de l'objet utilisateur créé est valide par la valeur logique renvoyée par user.valid?.
-Created_at et updated_at sont nil lorsque l'objet User est créé avec la nouvelle méthode, mais l'heure d'enregistrement
Est substitué.
-Si vous utilisez User.create, vous pouvez créer et enregistrer des objets en même temps.
##### Exercice
1. Notez que si vous ne mettez rien dans le nom et l'email, ce sera nul et ce sera NilClass.
user.email.class => String
user.name.class => String
2.ActiveSupport::TimeWithZone
user.created_at.class => ActiveSupport::TimeWithZone
user.updated_at.class => ActiveSupport::TimeWithZone
#### Rechercher des objets utilisateur
Résumez les points.
-Retournez l'utilisateur correspondant dans User.find (ID utilisateur)
-Retourne l'utilisateur correspondant dans User.find_by (attribut: valeur de recherche).
· User.first renvoie le premier utilisateur de la base de données
-Tous les enregistrements enregistrés dans la base de données dans User.all sont dans un format de type tableau.
Renvoyer comme (ActiveRecord_Relation).
##### Exercice
1. find_by_name a la même opération, mais utilise l'utilisation de passer un hachage à l'argument de base 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. Je veux connaître le nombre d'éléments (nombre) de User → Il semble être compté par longueur. → Vous pouvez compter si vous les connectez avec une chaîne de méthodes.
C'est ce qu'on appelle le typage canard que vous pouvez comprendre comment gérer une telle classe que vous ne connaissez pas en détail.
User.all.length User Load (0.2ms) SELECT "users".* FROM "users" => 2
#### Mettre à jour l'objet utilisateur
Il existe deux façons de mettre à jour le contenu d'un objet utilisateur
・ Remplacez et enregistrez directement
user.name = "takemo" => "takemo"
user.save
・ Mise à jour immédiate avec la méthode de mise à jour
user.update(name: "take",email: "[email protected]")
Lors de la mise à jour d'un seul attribut, transmettez le nom et la valeur de l'attribut au lieu du hachage comme ```update_attribute (: name, "take") ``.
Pour mettre à jour plus d'un attribut, passez un hachage comme ```update (nom: "take", email: "[email protected]") `` `.
À propos, les deux mettent à jour un attribut comme ```update_attribute (: name, "take") ```et ```update (name: "take") `` `
Ecrire sans utiliser de hachage comme argument (le premier) a également pour effet d'éviter la "vérification" des données qui seront apprises à partir de maintenant **. ** **
##### Exercice
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
### Validez l'utilisateur
Le mot «vérification» a été mentionné à plusieurs reprises dans les exercices précédents.
C'est une limite de données. Un utilisateur sans nom, une adresse e-mail mal formée ou un mot de passe trop court
Il ne doit pas être enregistré dans la base de données.
La validation est ce qui empêche cela.
#### Vérifier l'efficacité
Cette partie procèdera au développement piloté par les tests
Le premier test de modèle utilisateur ressemble à ceci
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
Voici la méthode de configuration qui est exécutée avant chaque test (un seul pour le moment)
Définissez un utilisateur de test dans la variable @user et
Les tests de test devraient être valides que @user est des données valides.
À ce stade, aucune validation n'a été ajoutée et toutes les données sont valides, le test passera donc définitivement.
#### **`models`**
```rails test
Exécutez uniquement les tests liés au modèle dans
Cependant, il est automatiquement testé par guard, et tous les tests sont exécutés même lorsqu'ils sont exécutés manuellement.
Je ne l'ai jamais utilisé ...
Il peut être utilisé lorsque le test lui-même augmente et devient lourd.
##### Exercice
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
C'est évident, mais ce serait une sorte de données car il n'y a pas de validation activée.
#### Vérifier l'existence
Essayez d'ajouter la validation la plus simple et la plus basique, présense
En ajoutant cela, il ne peut être activé que lorsque l'élément existe.
Écrivons d'abord le test.
test "name should be present" do @user.name = " " assert_not @user.valid? end
Dans ce test ajouté cette fois, mettez un blanc (n'existe pas) dans l'attribut de nom
@ user.valid? Avec assert_not (passe lorsque l'argument est faux)
Passe le test lorsque l'utilisateur n'est pas valide.
En d'autres termes
Mettez un espace vide et testez que l'utilisateur n'est pas valide si le nom n'existe pas.
Parce que le test échoue à ce stade
J'ai décidé d'ajouter une validation et de réussir le test.
class User < ApplicationRecord validates :name, presence: true end
Je pense qu'il y a pas mal de gens qui se mettent à écrire ici,
Si vous écrivez cette ligne sans l'omettre
#### **`validates(:name,{presence: true})`**
Passer: nom comme premier argument et hachage comme deuxième argument (facultatif) à la méthode validates. Rails fournit diverses abréviations pour plus d'efficacité. Ici le () de la méthode peut être omis, le dernier hachage de l'argument de la méthode peut omettre {}, Il utilise deux abréviations. Étant donné que ces abréviations continueront à apparaître comme une évidence à l'avenir J'expliquerai autant que possible, mais il est bon de s'y habituer maintenant.
J'ai ajouté la validation Non valide si le nom n'existe pas.
Vérifiez si la validation fonctionne sur la console.
>> 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
À propos, il ne peut pas être enregistré dans la base de données à l'état désactivé.
>> user.save
=> false
Un échec de cette manière crée un objet d'erreur et enregistre le message d'erreur.
>> user.errors.full_messages
=> ["Name can't be blank"]
Lorsque je quitte la console et exécute le test, le test réussit. Ecrivez un test pour l'attribut email, puis ajoutez une validation. (Développement d'essai routier)
Tester l'existence du courrier électronique
test "email should be present" do
@user.email = " "
assert_not @user.valid?
end
Le test échoue ici. Ajouter une validation par e-mail
validates :email, presence: true
Le test réussit.
##### Exercice
1. Je suis coincé dans la validation de l'existence du nom et de l'adresse e-mail
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. Les messages étant au format haché, vous pouvez les récupérer en spécifiant [: email].
u.errors.messages => {:name=>["can't be blank"], :email=>["can't be blank"]}
u.errors.messages[:email] => ["can't be blank"]
#### Vérifier la longueur
Pour le moment, le nom est limité à 50 caractères, ce qui est un nombre raisonnable de caractères.
Les adresses e-mail seront également limitées à 255 caractères, qui est la limite de caractères standard.
Écrivez un test avant d'ajouter la validation.
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
J'ai mis beaucoup de a pour gagner le nombre de personnages.
Le test échoue à ce stade.
validates :name, presence: true, length:{maximum: 50} validates :email, presence: true, length:{maximum: 255}
Cela validera le nombre de caractères et passera le test.
##### Exercice
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. Je me fâche quand c'est trop long.
user.errors.messages => {:name=>["is too long (maximum is 50 characters)"], :email=>["is too long (maximum is 255 characters)"]}
##### Vérifier le format
Si vous mettez les caractères appropriés dans l'adresse e-mail lors de la création d'un nouveau compte, ce qui est souvent vu sur divers sites
Je suis souvent en colère lorsque je dis "Veuillez saisir l'adresse e-mail correcte".
De cette manière, nous vérifierons si le format spécifié en tant qu'adresse e-mail est satisfait ou non en plus du nombre de caractères.
Vous pouvez facilement créer un tableau de chaînes de caractères en utilisant% w [], utilisez donc ceci pour créer une liste d'adresses de messagerie non valide.
Un test pour s'assurer qu'une adresse e-mail valide n'est pas interceptée lors de la validation
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
Un message d'erreur est ajouté avec le deuxième argument afin que vous puissiez voir quelle adresse e-mail le test a échoué.
Vient ensuite un test pour s'assurer que les adresses e-mail non valides sont fermement capturées lors de la validation
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
Le test échoue à ce stade.
Pour réussir le test
Ajoutez la validation de l'adresse e-mail.
Vous devez écrire une expression canonique pour vérifier le format de votre adresse e-mail.
Il y avait un site qui était très facile à comprendre, je vais donc le présenter.
https://murashun.jp/blog/20190215-01.html
Bien sûr, le Rubular introduit dans le didacticiel est également utile.
Définissez l'expression régulière d'Email. Dans Ruby, les constantes commencent par une lettre supérieure.
#### **`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
Supplément car il n'y avait aucune explication sur le tutoriel.
La partie [\ w + \ -.] Représente les caractères alphanumériques, les traits de soulignement, les points, les tirets et les points.
\ w correspond à des caractères alphanumériques et un trait de soulignement + -. Correspond à chacun, mais j'ai l'impression qu'il y en a un supplémentaire
C'est l'effet d'échapper au caractère immédiatement après, et le trait d'union immédiatement après a une signification particulière dans [].
Il a pour effet de spécifier une plage [a-z](a à z). Donc pour échapper et afficher comme l'original-
Puisqu'il est échappé avec , il devient une telle expression.
À ce stade, le test réussit.
Cette expression régulière ne fait pas apparaître une série de points comme sample @ gmail..com, je vais donc la corriger dans le prochain exercice.
1.
Faites correspondre le bon comme celui-ci.
/\A[\w+\-.]+@[a-z\d\-.]+(\.[a-z\d\-.]+)*\.[a-z]+\z/i
Il s'agit de `` (\. [A-z \ d \ -.] +) `` Et ajoute un autre motif avec .〇〇〇.
À peu près identique à 3.1
réduction
#### Vérifier l'unicité
L'adresse e-mail est utilisée comme nom d'utilisateur (par exemple lors de la connexion) et ne doit pas être dupliquée entre les utilisateurs.
Ici, une validation unique est ajoutée.
Avec User.new, la duplication ne se produit pas même si vous interrogez la base de données simplement en créant un objet en mémoire.
En d'autres termes, mettez les données A dans la base de données et testez exactement les mêmes données B.
test "email address should be unique" do duplicate_user = @user.dup @user.save assert_not duplicate_user.valid? end
Fixez ici
Les adresses e-mail sont généralement insensibles à la casse
[email protected] et [email protected] sont traités de la même manière.
Pour tester cela en même temps
test "email address should be unique" do duplicate_user = @user.dup duplicate_user.email.upcase! @user.save assert_not duplicate_user.valid? end
Mettez en valeur les adresses copiées et comparez.
Pour la validation, spécifiez simplement case_sensitive: false dans l'option d'unicité.
La validation est que l'adresse e-mail doit être unique mais pas sensible à la casse (les deux sont identiques).
Mais il y a encore des défauts.
Parce que la validation que nous ajoutons est vérifiée au stade de la création des données avant de les enregistrer dans la base de données.
Dans le cas peu probable où vous réussissez la vérification lorsqu'il y a beaucoup de trafic et un trafic intense lors de l'envoi successif des demandes d'enregistrement
Il sera enregistré dans la base de données tel quel.
Pour éviter cela, vous pouvez le forcer à être unique non seulement lors de la création de données, mais également lors de l'enregistrement des données.
Ceci est réalisé en ajoutant un index à la colonne e-mail de la base de données et en forçant l'index à être unique.
* Un index est comme un index de base de données, et l'ajouter améliorera la vitesse de recherche des données.
Je n'entrerai pas dans les détails ici, mais sachez que cela ne signifie pas que vous devez ajouter un index à toutes les données.
Créer un fichier de migration pour ajouter un index
```$ rails g migration add_index_to_users_email```
Alors que la migration et l'ajout d'un index ont forcé l'unicité de l'index de messagerie de la base de données
Étant donné que l'attribut email de fixture, qui sont les exemples de données de la base de données de test, est couvert, une erreur est générée.
Cet appareil n'est pas utilisé pour le moment non plus, supprimez donc le contenu
Jusqu'à présent, le test réussissait même si la valeur du fixture était incorrecte avant de s'enregistrer dans la base de données.
Parce que c'était un test pour la vérification des données (le montage est des données enregistrées dans le DB de test à l'avance)
Mais cela ne suffit toujours pas.
Selon la base de données, l'index peut ou non être sensible à la casse.
Dans la validation du modèle utilisateur, l'unicité: {case_sensitive: false} pourrait être utilisée.
Dans un tel cas, la méthode de conversion de toutes les données en minuscules avant de s'enregistrer dans la base de données est adoptée.
Utilisez la méthode before_save d'ActiveRecord pour spécifier que toutes les données doivent être converties en minuscules avant d'être enregistrées.
#### **` before_save { self.email.downcase! }`**
Cela appellera un rappel lors de l'enregistrement et tous les e-mails seront convertis en minuscules.
Par conséquent, unicité: {case_sensitive: false}
aussi
C'est correct de le remettre à vrai
Ce n'est pas un problème car il est toujours réduit lors de la sauvegarde.
#### **`S'il est remis à true, le test échouera.`**
```uniqueness
La validation est revenue au traitement du cas comme différent.
Par conséquent, le test restaure également la partie qui a été convertie en majuscules.
test "email address should be unique" do duplicate_user = @user.dup @user.save assert_not duplicate_user.valid? end
##### Exercice
1. Pour le moment, ne mettez que le résultat lorsque vous avez commenté.
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
Il est facile à comprendre car il y a des erreurs sous forme de valeurs attendues et de valeurs réelles.
Puisque le rappel sera appelé en décommentant et tout sera converti en minuscules puis sauvegardé.
Le test réussit également.
2. Omis car il était initialement écrit dans ```email.downcase! `` `.
Pour l'expliquer, ajouter! En fait une "méthode destructive", et dans ce cas, réduit le courrier électronique et le "remplace" avec le résultat.
### Ajouter un mot de passe sécurisé
Implémentez le mot de passe utilisateur.
Au lieu de simplement enregistrer le mot de passe dans la base de données, enregistrez la version hachée avec la fonction de hachage.
Obligatoire car le risque est considérablement inférieur à celui de l'enregistrement tel quel.
#### Mot de passe haché
Il existe une méthode pratique pour implémenter les mots de passe
```has_secure_password```80% est terminé simplement en ajoutant.
En appelant cette méthode dans le modèle
-Le mot de passe haché peut être enregistré dans l'attribut password_digest. "
・ En même temps que le mot de passe des attributs virtuels et password_confirmation deviennent disponibles
Une validation est également ajoutée pour voir si l'existence et les valeurs de ces deux attributs correspondent.
-La méthode ```authenticate``` peut être utilisée.
Bien sûr, il existe d'autres préparations, password_digest est évident mais doit être inclus dans le modèle.
Par conséquent, créez un fichier de migration pour ajouter password_digest.
#### **`string`**
```rails g migration add_password_digest_to_users password_digest
Rails interprète la modification apportée à la table users en terminant le fichier de migration par to_users.
Si vous écrivez également password_digest: string après le nom du fichier, il ajoutera le type de chaîne password_digest à la table users.
Il créera automatiquement une migration. Très pratique.
Comme mentionné ci-dessus, le fichier de migration n'a pas besoin d'être modifié, alors migrons-le tel quel.
De plus, bcrypt, qui est une fonction de hachage de pointe, est nécessaire pour le hachage de mot de passe.
Ajoutez bcrypt à votre Gemfile pour utiliser bcrypt.
#### **`gem 'bcrypt', '3.1.13'`**
Après l'ajout, appuyez sur bundle.
Maintenant que nous sommes prêts à utiliser has_secure_password, ajoutez `` has_secure_password '' au modèle utilisateur. La validation du fait que l'existence et la valeur des attributs virtuels password et password_confirmation sont identiques est bloquée. Passez la valeur de ces deux attributs à l'attribut @user du test.
>> 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
>> user1.errors.full_messages
=> ["Password can't be blank"]
Validez le nombre minimum de caractères (6 caractères) pour le mot de passe. Commencez par écrire le test. Écrivez un test pour lancer une erreur lorsque le mot de passe est vide ou contient moins de 6 caractères
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``` Utilise plusieurs affectations pour attribuer à deux éléments en même temps.
Maintenant que nous avons écrit le test, nous allons implémenter la validation. Puisqu'il s'agit du nombre minimum de caractères, utilisez l'option minimum, qui est l'opposé du maximum.
validates :password, presence: true, length:{minimum: 6}
Le test réussit lorsque la validation est ajoutée.
##### Exercice
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)"]}
#### Création et authentification des utilisateurs
Créez un nouvel utilisateur dans l'environnement de développement en vue de la création future de la page d'index.
La fonction de création d'utilisateur depuis le Web n'a pas encore été implémentée, alors ajoutez-la à l'aide de la console rails.
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", "$2a
12 xkZDNGfs2Dnjzbm5XxfCfu.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]>
Si vous regardez dans password_digest, le mot de passe haché est stocké.
user.password_digest => "$2a
12 xkZDNGfs2Dnjzbm5XxfCfu.sB3I4ug4PFtTHukKdp0EF9YLLsE5Sm"
De plus, comme expliqué précédemment, la méthode ```authenticate``` est activée par la méthode `` `has_secure_password```.
Je vais essayer.
user.authenticate("foo!baka") => false
Il renvoie false pour le mauvais mot de passe.
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]>
Renvoie un objet utilisateur avec le mot de passe correct. (vrai)
Vous pouvez également utiliser !! pour le convertir en une valeur logique et le renvoyer → `` `!! user.authenticate (" foobar ")` `
##### Exercice
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. Le mot de passe de l'attribut virtuel est vide, il est donc bloqué lors de la validation.
Le mot de passe précédemment saisi est haché et enregistré dans la base de données sous le nom password_digest, vous devez donc le saisir à chaque fois.
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. Vous pouvez utiliser la méthode update_attribute pour contourner la validation et mettre à jour la valeur directement.
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
### finalement
Validez les modifications jusqu'à présent dans Git
Poussez et déployez.
N'oubliez pas de migrer la base de données de l'environnement de production.
[Vers le chapitre précédent](https://qiita.com/take_webengineer/items/6949dc3131d4f34e27c0)
[Vers le chapitre suivant]()
Recommended Posts