[RUBY] [Rails] N'utilisez pas la méthode de sélection uniquement pour réduire les colonnes!

À propos de la méthode de sélection d'ActiveRecord

Lorsque vous obtenez des données avec ActiveRecord, vous obtenez essentiellement tous les éléments du tableau correspondant. Comme vous pouvez le voir dans le SQL à émettre, tous les éléments sont acquis avec *. Puisque tous les articles ont été acquis, n'importe quel article peut être référencé dans le traitement suivant.

pry(main)> user = User.first
  User Load (0.7ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User id: 1, name: "ham", created_at: "2020-03-10 01:03:37", updated_at: "2020-06-16 02:18:39">
pry(main)> user.id
=> 1
pry(main)> user.name
=> "ham"

Cependant, toutes les colonnes ne sont pas utilisées, alors pourquoi ne pas obtenir uniquement les colonnes nécessaires? Je pense qu'il y a aussi l'idée. Dans ce cas, vous pouvez affiner les colonnes à acquérir en utilisant la méthode appelée select. Pour plus d'informations sur select, reportez-vous au [Rails Guide](https://railsguides.jp/active_record_querying.html#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82% A3% E3% 83% BC% E3% 83% AB% E3% 83% 89% E3% 81% A0% E3% 81% 91% E3% 82% 92% E5% 8F% 96% E3% 82% 8A% Voir E5% 87% BA% E3% 81% 99).

Vous ne pouvez obtenir que les colonnes requises en spécifiant select. Bien entendu, les colonnes qui n'ont pas été acquises ne peuvent pas être référencées dans le traitement ultérieur.

pry(main)> user = User.select(:id, :created_at).first
  User Load (0.7ms)  SELECT `users`.`id`, `users`.`created_at` FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User id: 1, created_at: "2020-03-10 01:03:37">
pry(main)> user.id
=> 1
pry(main)> user.name
ActiveModel::MissingAttributeError: missing attribute: name
from /usr/local/bundle/gems/activemodel-6.0.3.2/lib/active_model/attribute.rb:221:in `value'

N'utilisez pas de sélection qui ne fait que réduire les colonnes!

C'est juste mon opinion personnelle, mais si vous développez avec plusieurs personnes comme le développement d'équipe, je pense qu'il vaut mieux ne pas utiliser select qui ne fait que réduire les colonnes.

Pourquoi?

Voir le code ci-dessous.

def hoge(user_id)
  #identifiant avec select,Obtenez uniquement le nom
  user = User.select(:id, :name).find(user_id)

  ...(Traitement divers)

  generate_response(user)
end

private

def generate_response(user)
  { id: user.id, name: user.name }
end

Et si vous décidiez plus tard d'ajouter un e-mail à la réponse de la méthode hoge? Supposons que le modèle User a une colonne email.

Vous avez probablement juste besoin de le trouver et d'ajouter un e-mail à generate_response! Je pense que je vais résoudre le problème comme suit.

def generate_response(user)
-  { id: current_user.id, name: current_user.name }
+  { id: current_user.id, name: current_user.name, email: current_user.email }
end

La correction est terminée! Cela a été fait en une seule ligne! !! Exécution du test! !! !!

pry(main)> { id: user.id, name: user.name, email: user.email }
ActiveModel::MissingAttributeError: missing attribute: email
from /usr/local/bundle/gems/activemodel-6.0.3.2/lib/active_model/attribute.rb:221:in `value'

cette? ?? Ça ne marche pas ... L'utilisateur destinataire est-il étrange? Suivez-moi ...

C'est vrai. Étant donné que la colonne d'acquisition est réduite par sélection, il est nécessaire d'y ajouter un e-mail. Si vous modifiez ce qui suit, cela fonctionnera.

def hoge(user_id)
  #identifiant avec select,Obtenez uniquement le nom
-  user = User.select(:id, :name).find(user_id)
+  user = User.select(:id, :name, :email).find(user_id)

Le test s'est bien passé!

pry(main)> { id: user.id, name: user.name, email: user.email }
=> {:id=>1, :name=>"hoge", :email=>"[email protected]"}

Qu'est-ce que tu penses?

Si vous utilisez Rails ActiveRecord, vous obtiendrez toutes les colonnes de base, donc je pense que beaucoup de gens en sont accro une fois comme mentionné ci-dessus.

Ce n'est peut-être pas autant d'efforts à chaque fois, mais la même chose se produit à chaque fois si le système est continuellement développé. C'est un bon prix. Dans le pire des cas, cela peut même passer inaperçu et créer des bugs.

Est-il nécessaire de mettre en œuvre cette sélection pour augmenter le coût de développement et le risque de bugs? Je préfère un code que les autres ont du mal à mal comprendre, même s'il est un peu moins optimal. C'est pourquoi je pense qu'il vaut mieux ne pas utiliser select, que j'utilise juste pour affiner les colonnes.

Comment utiliser select

C'est devenu un article qui nie complètement l'existence de select, mais il a bien sûr quelques utilisations. C'est lorsque la fonction d'agrégation est utilisée comme indiqué ci-dessous.

users_group_by_name = User.select('name, count(*) AS cnt').group(:name)
users_group_by_name.each do |u|
  p u.name
  # u.Vous pouvez obtenir le décompte avec cnt
  p u.cnt
end

Cependant, même dans ce cas, il est fort probable que vous vous mépreniez si le nom de la variable est changé en ʻusers`, il est donc préférable d'utiliser un nom de variable compréhensible.

Aussi, parfois je permet d'accéder directement à la table à laquelle j'ai rejoint en utilisant select, mais c'est aussi très difficile à comprendre, donc je pense qu'il vaut mieux l'arrêter.

review = Review.select('reviews.id, users.name').joins(:user).find_by(id: 1)
#Maintenant utilisateur.peut accéder au nom
review.name

Accès via l'association normalement ou implémenter un délégué.

app/models/review.rb


review = Review.find_by(id: 1)
#Accès via association
review.user.name
#Ou définir un délégué dans le modèle de révision(delegate :name, to: :user, prefix: true)
review.user_name

Résumé

Cet article était axé sur la sélection, mais je pense qu'il est important d'écrire un code facile à comprendre pour les autres (difficile à mal comprendre) dans le développement d'équipe où plusieurs personnes touchent le même code. L'écriture d'un code facile à lire (difficile à mal comprendre) accélérera le développement et réduira les bogues.

Recommended Posts

[Rails] N'utilisez pas la méthode de sélection uniquement pour réduire les colonnes!
[Rails] Comment utiliser la méthode de la carte
Utilisez la méthode where pour affiner en vous référant à la valeur d'un autre modèle.
[Rails] Je ne sais pas comment utiliser le modèle ...
Comment utiliser la méthode link_to
Comment utiliser la méthode include?
Comment utiliser la méthode form_with
[Java] Comment utiliser la méthode toString ()
[Rails] Comment utiliser la méthode d'assistance, confimartion
[Rails] Comment utiliser les boîtes de sélection dans Ransack
Lorsque vous souhaitez utiliser la méthode à l'extérieur
Sortie de la façon d'utiliser la méthode slice
[Introduction à Ruby] Comment utiliser la méthode slice
[rails] Comment utiliser la méthode d'assistance de devise before_action: authenticate_user!
Utilisez collection_select pour extraire les données stockées dans Active_Hash
Je souhaite utiliser la méthode de désinfection autre que View.
Que faire si la commande rails devient inutilisable
[Rails] Comment utiliser enum
[Rails] Comment utiliser enum
Comment utiliser la jonction de rails
[Rails] Comment utiliser la validation
[Rails] Comment utiliser authenticate_user!
Array.map facile à utiliser (&: méthode)
[Rails] Comment utiliser Scope
Utilisez Modifier # isStatic pour déterminer si la méthode [Reflection] est statique.
[Rails] Comment omettre l'affichage de la chaîne de caractères de la méthode link_to
J'ai essayé de comprendre comment la méthode des rails "link_to" est définie
Comment affiner le format d'image de la galerie sur Android, puis sélectionner et importer plusieurs images
[Rails] Procédure d'implémentation de la fonction pour taguer les posts sans gem + la fonction pour affiner et afficher les posts par tags
[Rails] Comment utiliser la "devise" des gemmes
[Rails] Comment utiliser l'appareil (Remarque)
[Rails] Comment utiliser les messages flash
[Java] Comment utiliser la méthode de jointure
Comment utiliser la classe wrapper
Comment utiliser Ruby on Rails
J'ai essayé d'expliquer la méthode
[Rails] Comment utiliser Active Storage
[Rails 6] détruit en utilisant la méthode des ressources
[Introduction aux rails] Comment utiliser le rendu
Comment utiliser la méthode Ruby inject
Utilisez la méthode de permutation pour que tous les utilisateurs par défaut se suivent
[Rails] Utilisez le dispositif pour obtenir des informations sur l'utilisateur actuellement connecté
À vous à qui on a dit "Ne pas utiliser Stream API" dans le champ
[Rails] Comment résoudre le décalage temporel de created_at après la méthode de sauvegarde