Pour le moment, j'ai pu confirmer que la création et la lecture fonctionnent la dernière fois. De là, suivez cette procédure
Dans cet article, je vais implémenter 1 et 2 pour le moment, et après 3. je vais passer aux articles suivants et suivants.
Écrire un document Excluez l'erreur telle qu'elle apparaît dans le fichier de migration.
.rubocop.yml peut être exclu de cette manière, mais si vous excluez ce dont vous avez besoin à l'origine, cela brisera le sens de l'observation des normes de codage en premier lieu, alors discutons-en fermement lors de l'ajout dans le développement d'équipe. ..
diff:.rubocop.yml
+ #Documentation
+ Style/Documentation:
+  Exclude:
+    - "db/migrate/**/*"
...
Comme Test Driven Development (TDD), le premier est le test de Red. Puisque la validation n'est pas implémentée, je vais faire quelque chose qui sera rouge même si j'écris un test et l'exécute.
Je vais l'écrire dans une coche Rails normale sans utiliser une seule fois factory_bot.
spec/models/post_spec.rb
# frozen_string_literal: true
require "rails_helper"
RSpec.describe Post, type: :model do
  describe "subject" do
    context "Lorsque vide" do
      it "Devenir invalide" do
        post = Post.new(subject: "", body: "fuga")
        expect(post).not_to be_valid
      end
    end
  end
end
Donc, le code ci-dessus teste que "il devient invalide lorsque le sujet est vide". Mais jusqu'à présent, je n'ai pas validé le sujet du modèle de publication, donc le message est valide et le test "invalide" échouera.
$ rspec spec/models/post_spec.rb
...
Finished in 0.07805 seconds (files took 3.53 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/models/post_spec.rb:8 #Non valide lorsque le sujet du message est vide
ec2-user:~/environment/bbs (master) $ rspec
Essayons de nous inscrire même si le sujet est vide.
$ rails c
[1] pry(main)> Post.create!(subject: "", body: "hoge")
   (0.1ms)  BEGIN
  Post Create (2.5ms)  INSERT INTO "posts" ("subject", "body", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["subject", ""], ["body", "hoge"], ["created_at", "2020-09-06 01:07:52.628768"], ["updated_at", "2020-09-06 01:07:52.628768"]]
   (0.9ms)  COMMIT
=> #<Post:0x0000000005760700
 id: 2,
 subject: "",
 body: "hoge",
 created_at: Sun, 06 Sep 2020 01:07:52 UTC +00:00,
 updated_at: Sun, 06 Sep 2020 01:07:52 UTC +00:00>
Vous l'avez sauvegardé.
Au fait, sans utiliser de description ni de contexte
spec/models/post_spec.rb
# frozen_string_literal: true
require "rails_helper"
RSpec.describe Post, type: :model do
  it "Invalide lorsque le sujet est vide" do
    post = Post.new(subject: "", body: "fuga")
    expect(post).not_to be_valid
  end
end
Le comportement du code de test est presque le même. C'est parce que vous pouvez tester en écrivant expect dans le bloc it. Cependant, il devient difficile à comprendre lors de la description de la même colonne et des mêmes conditions de validation par regroupement, il est donc fondamentalement recommandé de décrire en imbriquant la description et le contexte.
app/models/post.rb
 class Post < ApplicationRecord
+  validates :subject, presence: true
 end
Vous ne pouvez plus vous inscrire avec vrai ou vide pour la présence de la colonne sujet.
Essayons.
$ rails c
[1] pry(main)> Post.create!(subject: "", body: "hoge")
ActiveRecord::RecordInvalid: Validation failed: Subject can't be blank
from /home/ec2-user/.rvm/gems/ruby-2.7.1/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:80:in `raise_validation_error'
Je ne peux pas m'inscrire.
$ rspec ./spec/models/post_spec.rb 
...
Finished in 0.05053 seconds (files took 1.63 seconds to load)
1 example, 0 failures
Le test a également réussi.
Comme ce serait un problème si le nombre de caractères pouvait être enregistré indéfiniment, nous ajouterons une limite. C'est aussi le premier test. J'écrirai un test avec un plan pour ajouter la validation qu'il est OK s'il est de 30 caractères ou moins et NG s'il est de 31 caractères ou plus.
spec/models/post_spec.rb
         expect(post).not_to be_valid
       end
     end
+    context "par maxlength" do
+      context "Pour 30 caractères" do
+        it "Devenir valide" do
+          post = Post.new(subject: "Ah" * 30, body: "fuga")
+          expect(post).to be_valid
+        end
+      end
+      context "Pour 31 caractères" do
+        it "Devenir invalide" do
+          post = Post.new(subject: "Ah" * 31, body: "fuga")
+          expect(post).not_to be_valid
+        end
+      end
+    end
   end
 end
Faisons un test.
$ rspec ./spec/models/post_spec.rb 
...
Finished in 0.03204 seconds (files took 1.42 seconds to load)
3 examples, 1 failure
Failed examples:
rspec ./spec/models/post_spec.rb:21 #La longueur maximale du sujet du message le rend invalide pour 31 caractères
Je n'ai pas encore ajouté de validation, donc 30 caractères passeront mais 31 caractères seront de la mousse. Ajoutez une validation au modèle.
app/models/post.rb
 class Post < ApplicationRecord
-  validates :subject, presence: true
+  validates :subject, presence: true, length: { maximum: 30 }
 end
$ rspec ./spec/models/post_spec.rb 
...
Finished in 0.02201 seconds (files took 1.4 seconds to load)
3 examples, 0 failures
Vous avez réussi le test.
Cela entraînera une erreur à 31 caractères. Essayez-le avec rails c.
Par exemple, dans le code de test ci-dessus
  post = Post.new(subject: "Ah" * 30, body: "fuga")
Cependant, il est difficile de spécifier le corps à chaque fois. Ce n'est toujours pas grave s'il s'agit de 2 colonnes, mais s'il dépasse 10 colonnes, le code sera inutilement long. À ce moment-là, utilisez factoryBot.
Le factoryBot regarde sous spec / usines /. Cette fois, il n'est pas nécessaire de changer la valeur initiale lors de la création du modèle, mais regardons le contenu.
spec/factories/posts.rb
# frozen_string_literal: true
FactoryBot.define do
  factory :post do
    subject { "MyString" }
    body { "MyText" }
  end
end
Modifiez le fichier post_spec.rb.
spec/models/post_spec.rb
   describe "subject" do
     context "Lorsque vide" do
       it "Devenir invalide" do
-        post = Post.new(subject: "", body: "fuga")
+        post = build(:post, subject: "")
         expect(post).not_to be_valid
       end
     end
     context "par maxlength" do
       context "Pour 30 caractères" do
         it "Devenir valide" do
-          post = Post.new(subject: "Ah" * 30, body: "fuga")
+          post = build(:post, subject: "Ah" * 30)
           expect(post).to be_valid
         end
       end
       context "Pour 31 caractères" do
         it "Devenir invalide" do
-          post = Post.new(subject: "Ah" * 31, body: "fuga")
+          post = build(:post, subject: "Ah" * 31)
           expect(post).not_to be_valid
         end
       end
build est l'équivalent de .new en utilisant factoryBot. Il n'est pas enregistré dans la base de données.
Dans ce cas, le sujet est spécifié, mais le corps n'est pas spécifié, donc le corps du factoryBot contiendra «" MyText "».
Exécutez également un test pour chaque modification pour vous assurer qu'elle est correcte.
Pour le moment, essayez de le changer comme suit.
spec/models/post_spec.rb
 RSpec.describe Post, type: :model do
   describe "subject" do
     context "Lorsque vide" do
+      let(:post) do
+        build(:post, subject: "")
+      end
       it "Devenir invalide" do
-        post = build(:post, subject: "")
         expect(post).not_to be_valid
       end
     end
     context "par maxlength" do
       context "Pour 30 caractères" do
+        let(:post) do
+          build(:post, subject: "Ah" * 30)
+        end
         it "Devenir valide" do
-          post = build(:post, subject: "Ah" * 30)
           expect(post).to be_valid
         end
       end
       context "Pour 31 caractères" do
+        let(:post) do
+          build(:post, subject: "Ah" * 31)
+        end
         it "Devenir invalide" do
-          post = build(:post, subject: "Ah" * 31)
           expect(post).not_to be_valid
         end
       end
let est une variable limitée à la portée du même bloc de description ou de contexte. Dans Ruby, la dernière expression évaluée est la valeur de retour, donc
  let(:post) do
    build(:post, subject: "Ah" * 31)
  end
Dans le cas de, le post du résultat de l'exécution de la construction devient une variable appelée post par let (: post).
Implémentons le test et la validation de la limite obligatoire et de la limite de 100 caractères ou moins sur le corps.
spec/models/post_spec.rb
# frozen_string_literal: true
require "rails_helper"
RSpec.describe Post, type: :model do
  describe "subject" do
    context "Lorsque vide" do
      let(:post) do
        build(:post, subject: "")
      end
      it "Devenir invalide" do
        expect(post).not_to be_valid
      end
    end
    context "par maxlength" do
      context "Pour 30 caractères" do
        let(:post) do
          build(:post, subject: "Ah" * 30)
        end
        it "Devenir valide" do
          expect(post).to be_valid
        end
      end
      context "Pour 31 caractères" do
        let(:post) do
          build(:post, subject: "Ah" * 31)
        end
        it "Devenir invalide" do
          expect(post).not_to be_valid
        end
      end
    end
  end
  describe "body" do
    context "Lorsque vide" do
      let(:post) do
        build(:post, body: "")
      end
      it "Devenir invalide" do
        expect(post).not_to be_valid
      end
    end
    context "par maxlength" do
      context "Pour 100 caractères" do
        let(:post) do
          build(:post, body: "Ah" * 100)
        end
        it "Devenir valide" do
          expect(post).to be_valid
        end
      end
      context "Pour 101 caractères" do
        let(:post) do
          build(:post, body: "Ah" * 101)
        end
        it "Devenir invalide" do
          expect(post).not_to be_valid
        end
      end
    end
  end
end
Si vous exécutez rspec à ce stade, ce sera de la mousse
app/models/post.rb
# frozen_string_literal: true
#
#Après la classe
#
class Post < ApplicationRecord
  validates :subject, presence: true, length: { maximum: 30 }
  validates :body, presence: true, length: { maximum: 100 }
end
Réglage d'exclusion car le rubocop est de la mousse. Il vaut mieux ne pas être trop strict car le test peut être contre-productif si vous respectez les normes DRY et de codage.
diff:.rubocop.yml
+ #Longueur de bloc
+ Metrics/BlockLength:
+   Exclude:
+     - "spec/**/*"
À ce stade, si vous exécutez rspec et rubocop, il passera.
[Vers la table de sérialisation]
Recommended Posts