[RUBY] Créer une API de tableau d'affichage avec autorisation dans Rails 6 # 12 Association d'utilisateur et de publication

Création d'une API de tableau d'affichage avec autorisation de certification dans Rails 6 # 11 Test et validation du modèle utilisateur ajoutés

Associer de la publication à l'utilisateur

Associer le poste et l'utilisateur. J'omettrai l'explication de la signification car il est supposé que le lecteur visé a terminé le didacticiel Rails, mais ajoutons appartient_to: user pour publier et has_many: posts à l'utilisateur.

$ rails g migration AddUserIdToPosts user:references

S'il y a un enregistrement, il sera pris dans la contrainte non nulle et la migration entraînera une erreur, donc db: reset sera effectué (approximatif)

$ rails db:reset
$ rails db:migrate

app/models/post.rb


...
 class Post < ApplicationRecord
+  belongs_to :user
+
...

app/models/user.rb


...
   include DeviseTokenAuth::Concerns::User

 
+  has_many :posts, dependent: :destroy
+
...

Après avoir associé les deux tables, essayez d'utiliser rails c pour voir si cela fonctionne.

$ rails  c
[1] pry(main)> user = User.create!(name: "hoge", email: "[email protected]",  password: "password")
[2] pry(main)> post = Post.create!(subject: "test", body: "testtest", user: user)
[3] pry(main)> user.posts
  Post Load (0.3ms)  SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = $1  [["user_id", 1]]
=> [#<Post:0x000000000488dbb0
  id: 1,
  subject: "test",
  body: "testtest",
  created_at: Tue, 08 Sep 2020 08:36:20 UTC +00:00,
  updated_at: Tue, 08 Sep 2020 08:36:20 UTC +00:00,
  user_id: 1>]
[4] pry(main)> post.user
=> #<User id: 1, provider: "email", uid: "[email protected]", name: "hoge", email: "[email protected]", created_at: "2020-09-08 08:36:11", updated_at: "2020-09-08 08:36:11">

Apparemment, vous pouvez appeler en toute sécurité les messages de l'utilisateur et de l'utilisateur à partir de la publication.

Corriger le sérialiseur de publication

Je souhaite obtenir l'identifiant, le nom et l'adresse e-mail de l'utilisateur à partir de l'API posts. À ce moment-là, le sérialiseur et le contrôleur doivent être corrigés. Au minimum, vous n'avez besoin que du sérialiseur pour fonctionner, mais sachez que si vous ne modifiez pas le contrôleur, une grande quantité de SQL inutile appelé problème N + 1 coulera et les performances chuteront.

app/serializers/post_serializer.rb


...
 class PostSerializer < ActiveModel::Serializer
   attributes :id, :subject, :body
+  belongs_to :user

Cela incitera l'utilisateur à rester ensemble.

$ curl localhost:8080/v1/posts/1
{"post":{"id":1,"subject":"test","body":"testtest","user":{"id":1,"provider":"email","uid":"[email protected]","name":"hoge","email":"[email protected]","created_at":"2020-09-08T08:36:11.972Z","updated_at":"2020-09-08T08:36:11.972Z"}}}

C'est bien qu'ils restent ensemble, mais j'ai beaucoup d'informations inutiles de la part de l'utilisateur. Il n'y a pas de sérialiseur pour l'utilisateur, ajoutons-le donc.

Créer un sérialiseur utilisateur

Le sérialiseur est généré automatiquement lorsque le modèle est créé, mais comme le modèle a été créé avec devise_token_auth, la commande est exécutée manuellement. De plus, activeModelSerializer ne fonctionne pas pour la réponse json du contrôleur générée automatiquement par devise_token_auth. Si vous voulez l'activer, vous devez remplacer le contrôleur de périphérique, mais cette fois je l'omettrai.

Du modèle de poste au futur utilisateur

$ rails g serializer user

app/serializers/user_serializer.rb


# frozen_string_literal: true

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name, :email
end
$ curl localhost:8080/v1/posts/1
{"post":{"id":1,"subject":"test","body":"testtest","user":{"id":1,"name":"hoge","email":"[email protected]"}}}

C'est OK pour le moment.

Traiter les problèmes N + 1

Maintenant, créons plusieurs utilisateurs / plusieurs données post avec rails c et appuyez sur curl localhost: 8080 / v1 / posts. Je peux obtenir les données en toute sécurité, mais lorsque je passe au terminal, il démarre avec rails s ...

Started GET "/v1/posts" for 127.0.0.1 at 2020-09-08 08:48:08 +0000
Processing by V1::PostsController#index as */*
  Post Load (0.3ms)  SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC LIMIT $1  [["LIMIT", 20]]
  ↳ app/controllers/v1/posts_controller.rb:12:in `index'
[active_model_serializers]   User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
[active_model_serializers]   ↳ app/controllers/v1/posts_controller.rb:12:in `index'
[active_model_serializers]   CACHE User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
[active_model_serializers]   ↳ app/controllers/v1/posts_controller.rb:12:in `index'
[active_model_serializers]   CACHE User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
[active_model_serializers]   ↳ app/controllers/v1/posts_controller.rb:12:in `index'
[active_model_serializers]   User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
...
[active_model_serializers]   ↳ app/controllers/v1/posts_controller.rb:12:in `index'
[active_model_serializers]   CACHE User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
[active_model_serializers]   ↳ app/controllers/v1/posts_controller.rb:12:in `index'
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::Json (30.42ms)
Completed 200 OK in 34ms (Views: 32.5ms | ActiveRecord: 0.8ms | Allocations: 21448)

Bien que omis, une grande quantité de SQL s'écoule de cette manière. C'est le problème N + 1.

Puisque l'utilisateur associé à la publication est trouvé et récupéré un enregistrement à la fois, une grande quantité de flux SQL inutiles.

C'est OK si vous l'incluez au moment où Post.all arrive.

app/controllers/v1/posts_controller.rb


     def index
-      posts = Post.order(created_at: :desc).limit(20)
+      posts = Post.includes(:user).order(created_at: :desc).limit(20)
       render json: posts
     end
Started GET "/v1/posts" for 127.0.0.1 at 2020-09-08 08:51:50 +0000
Processing by V1::PostsController#index as */*
  Post Load (0.2ms)  SELECT "posts".* FROM "posts" ORDER BY "posts"."created_at" DESC LIMIT $1  [["LIMIT", 20]]
  ↳ app/controllers/v1/posts_controller.rb:12:in `index'
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3)  [["id", 3], ["id", 2], ["id", 1]]
  ↳ app/controllers/v1/posts_controller.rb:12:in `index'
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::Json (5.32ms)
Completed 200 OK in 41ms (Views: 32.7ms | ActiveRecord: 5.1ms | Allocations: 17394)

Il y a maintenant deux utilisateurs et messages, un pour chaque table.

Pour le moment, le mouvement de l'application semble avoir été figé, mais en fait, si vous déplacez rspec dans cet état, il se moussera largement. La prochaine fois, nous vérifierons rspec et seed.

A continué

Création d'une API de tableau d'affichage avec autorisation de certification dans Rails 6 # 13 Accorder l'en-tête d'authentification [Vers la table de sérialisation]

Recommended Posts

Créer une API de tableau d'affichage avec autorisation dans Rails 6 # 12 Association d'utilisateur et de publication
Construire une API de tableau d'affichage avec certification et autorisation avec Rails 6 # 18 ・ Implémentation du contrôleur de l'utilisateur final
Créer une API de tableau d'affichage avec autorisation de certification dans Rails 6 # 11 Test et validation du modèle utilisateur ajoutés
Créez une API de tableau d'affichage avec certification et autorisation avec Rails 6 # 1 Construction de l'environnement
Créer une API de tableau d'affichage avec autorisation de certification dans Rails 6 # 13 Accorder l'en-tête d'authentification
# 4 post-validation et mise en œuvre de test pour créer une API de tableau d'affichage avec certification et autorisation dans Rails 6
Créez une API de tableau d'affichage avec certification et autorisation avec Rails 6 # 3 RSpec, FactoryBot introduit et post-modèle
Construire une API de tableau d'affichage avec certification et autorisation dans le contrôleur Rails 6 # 5, implémentation des routes
Introduction de # 10 devise_token_auth pour créer une API de tableau d'affichage avec autorisation d'authentification dans Rails 6
Présentation de # 2 git et rubocop pour créer une API de tableau d'affichage avec autorisation d'authentification dans Rails
Introduction de l'expert n ° 15 pour créer une API de tableau d'affichage avec certification et autorisation dans Rails 6
Créez une API de tableau d'affichage avec certification et autorisation dans Rails 6 # 17 Ajoutez des privilèges d'administrateur
Construire une API de tableau d'affichage avec certification et autorisation dans Rails 6 # 14 Seed Affichage du temps d'exécution
# 16 paramètre de stratégie pour créer une API de tableau d'affichage avec autorisation de certification dans Rails 6
Présentation du sérialiseur n ° 9 pour créer une API de tableau d'affichage avec certification et autorisation dans Rails 6
Créez une API de tableau d'affichage avec certification et autorisation dans Rails 6 # 6 show, créez une implémentation
Créer une API de tableau d'affichage avec autorisation de certification dans la mise à jour Rails 6 # 7, détruire l'implémentation
[Rails] Obtenez access_token au moment de l'authentification Twitter avec Sorcery et enregistrez-le dans la base de données
Une note de ce sur quoi j'ai trébuché et remarqué en rattrapant Laravel de Rails
[Procédure d'implémentation] Créer une fonction d'authentification utilisateur à l'aide de sorcellerie dans Rails
J'ai essayé d'implémenter l'API Rails avec TDD par RSpec. part2 -authentification de l'utilisateur-
J'ai essayé de créer une fonction de groupe (babillard) avec Rails
[Rails 6] Enregistrez-vous et connectez-vous avec l'authentification Devise + SNS (plusieurs liens sont autorisés)
Comment obtenir l'ID d'un utilisateur qui s'est authentifié avec Firebase dans Swift
Valider le jeton d'ID d'un utilisateur authentifié par AWS Cognito en Java
Créez un tableau d'affichage simple avec Java + MySQL
Essayez de créer un babillard en Java
[Rails] Classement et pagination par J'aime
[Rails] [Docker] Le copier-coller est OK! Comment créer un environnement de développement Rails avec Docker