[RUBY] Relisez le guide des rails (vue d'ensemble du contrôleur d'action)

5. Session

Un objet de session est créé pour chaque utilisateur dans l'application Rails et les informations de la demande précédente peuvent être utilisées en continu. Les sessions ne sont disponibles que dans Controller et View, et une petite quantité de données est stockée dans la session.
Vous pouvez choisir parmi les destinations de stockage suivantes pour la session.

--ʻActionDispatch :: Session :: CookieStore: Enregistre toutes les sessions dans le cookie du navigateur côté client --ʻActionDispatch :: Session :: CacheStore: enregistrer les données dans le cache Rails --ʻActionDispatch :: Session :: ActiveRecordStore: Enregistrer dans la base de données en utilisant Active Record (nécessite la gemme activerecord-session_store) --ʻActionDispatch :: Session :: MemCacheStore: Stocke les données dans un cluster memcached (cette implémentation est ancienne et vous devriez considérer CacheStore)

La session a un identifiant unique et le stocke dans cookie. Passer l'ID de session comme ʻURL est très dangereux pour la sécurité, donc Rails` ne le permet pas par défaut. Par conséquent, l'ID de session doit être passé en tant que «cookie».

De nombreux SessionStore (ID de session) sont utilisés pour récupérer les données de session sur le serveur. Cependant, seul CookieStore stocke toutes les données de session dans cookie lui-même (l'ID de session peut être utilisé si nécessaire).
CookieStore est utilisé par défaut dans Rails et est le magasin de session recommandé dans Rails.
L'avantage de «CookieStore» est

--Très léger ――Le fait qu'aucune préparation n'est requise lors de sa première utilisation

Les données du «cookie» reçoivent une signature cryptée pour empêcher toute falsification, et le cookie lui-même est crypté, de sorte que le contenu est lu par d'autres. (Le cookie falsifié sera rejeté par Rails)

Environ 4 Ko de données peuvent être stockées dans le CookieStore, ce qui est une capacité suffisante. Quel que soit le type de stockage de session utilisé, il n'est pas souhaitable de stocker une grande quantité de données dans une session.

Considérez ʻActionDispatch :: Session :: CacheStore` si la session utilisateur ne contient pas de données importantes ou si vous n'avez pas besoin de stocker la session pendant une longue période.
Le mérite est que l'infrastructure de cache existante peut être utilisée telle quelle car elle est enregistrée à l'aide de l'implémentation de cache définie dans l'application Web. Par conséquent, aucune préparation particulière n'est requise.
L'inconvénient est que la session est de courte durée et peut disparaître à tout moment.

5-1. Accéder à la session

L'accès à la session est rendu possible en utilisant la méthode d'instance session dans le contrôleur. Les valeurs de session sont stockées à l'aide de paires clé / valeur de type hachage.

class ApplicationController < ActionController::Base

  private

  #Rechercher des utilisateurs par identifiant stocké dans une session à clé
  # :current_user_id est un moyen standard de gérer les connexions utilisateur dans les applications Rails.
  #Lorsque vous vous connectez, la valeur de session est définie et
  #La valeur de session est supprimée lorsque vous vous déconnectez.

<Méthode ①>

  def current_user
    @current_user ||= session[:current_user_id] &&
      User.find_by(id: session[:current_user_id])
  end

<Méthode ②>

  def current_user
    if session[:current_user_id]
      @current_user ||= User.find_by(id: session[:current_user_id])
    end
  end

end

Si vous souhaitez enregistrer quelque chose dans la session, attribuez une clé comme un hachage.

class LoginsController < ApplicationController
  # "Create" a login, aka "log the user in"
  def create
    if user = User.authenticate(params[:username], params[:password])
      #Enregistrez l'ID utilisateur de session et
      #Rendez-le disponible pour de futures demandes
      session[:current_user_id] = user.id
      redirect_to root_url
    end
  end
end

Si vous souhaitez supprimer certaines des données de la session, supprimez cette paire clé-valeur.

class LoginsController < ApplicationController
  #Supprimer la connexion(=Se déconnecter)
  def destroy
    #Supprimer l'ID utilisateur de l'ID de session
    session.delete(:current_user_id)
    #Effacer l'utilisateur actuel qui a été noté
    @_current_user = nil
    redirect_to root_url
  end
end

Utilisez reset_session pour réinitialiser toute la session.

5-2. Flash flash est une partie spéciale de la session qui est effacée à chaque demande. Il a une fonctionnalité qui ne peut être référencé qu'immédiatement après la demande, et un message d'erreur est passé à view.
flash est accessible sous forme de hachage et est appelé une instance FlashHash. À titre d'exemple, traitons de l'opération de déconnexion. En utilisant le flash sur le contrôleur, vous pouvez envoyer le message à afficher dans la demande suivante.

class LoginsController < ApplicationController
  def destroy
    session.delete(:current_user_id)
    flash[:notice] = "You have successfully logged out."
    redirect_to root_url
  end
end

Le message flash peut également être attribué dans le cadre de la redirection. En plus de : notice et: alert comme options, general: flash peut également être utilisé.

redirect_to root_url, notice: "You have successfully logged out."
redirect_to root_url, alert: "You're stuck here!"
redirect_to root_url, flash: { referral_code: 1234 }
  1. Cookie Les applications Web peuvent stocker une petite quantité de données appelées «cookie» côté client (navigateur). Puisque «HTTP» est un protocole «sans état», il n'y a fondamentalement aucune association entre les demandes, mais avec un «cookie», vous pouvez utiliser entre les demandes (ou même entre les sessions). ) Ces données seront conservées. Dans Rails, vous pouvez facilement accéder aux cookies en utilisant la méthode cookies. La méthode d'accès est très similaire à celle d'une session et se comporte comme un hachage.
class CommentsController < ApplicationController
  def new
    #Si le nom de l'auteur du commentaire reste dans le cookie, il sera automatiquement saisi dans le champ
    @comment = Comment.new(author: cookies[:commenter_name])
  end

  def create
    @comment = Comment.new(params[:comment])
    if @comment.save
      flash[:notice] = "Thanks for your comment!"
      if params[:remember_name]
        #Commentaire Enregistrez le nom de l'auteur
        cookies[:commenter_name] = @comment.author
      else
        #Commentaire Supprimer le nom de l'auteur s'il reste dans le cookie
        cookies.delete(:commenter_name)
      end
      redirect_to @comment.article
    else
      render action: "new"
    end
  end
end

Lors de la suppression d'une session, elle a été supprimée en spécifiant «nil» comme clé, mais lors de la suppression de «cookies», vous devez utiliser «cookies.delete (: key)» au lieu de cette méthode.

Les «Rails» peuvent également utiliser des «cookies jar» signés et des «cookies jar» chiffrés pour stocker des données sensibles.

Ces cookies spéciaux utilisent un sérialiseur pour convertir la valeur en chaîne et l'enregistrer, puis effectuer une conversion déverse (désérialiser) en lecture pour la renvoyer à un objet Ruby.

Rails.application.config.action_dispatch.cookies_serializer = :json

Le sérialiseur par défaut pour les nouvelles applications est : json.

Il est recommandé de ne stocker que des "données simples" telles que des chaînes et des nombres dans cookie. Si vous devez stocker un objet complexe dans cookie, vous devez vous occuper de la conversion lors de la lecture de la valeur de cookie dans une requête ultérieure.

Il en va de même pour les hachages session et flash lors de l'utilisation du magasin de session cookie.

7. Sortie des données XML et JSON

Grâce à ʻActionController, il est très facile de sortir (rendre) les données XML et les données JSON`. Le contrôleur généré à l'aide de "scaffold" est le suivant.

class UsersController < ApplicationController
  def index
    @users = User.all
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render xml: @users }
      format.json { render json: @users }
    end
  end
end

Notez que dans le code ci-dessus, il est dit «render xml: @ users» au lieu de «render xml: @ users.to_xml». Rails appellera automatiquement to_xml si l'objet n'est pas de type String.

.to_xml Une méthode pour convertir un tableau ou un hachage au format XML.

array.to_xml([option])
hassh.to_xml([option])

8. Filtre

Un filtre est une méthode qui est exécutée «avant», «après» ou «à la fois immédiatement avant et autour» d'une action dans le contrôleur.

Le filtre est hérité, donc si vous définissez le filtre dans le contrôleur d'application, le filtre sera efficace dans tous les contrôleurs de l'application.

Une utilisation courante des filtres «avant» consiste à demander à un utilisateur de se connecter avant d'effectuer une action. Cette méthode de filtrage ressemble à ceci:

class ApplicationController < ActionController::Base
  before_action :require_login

  private

  def require_login
    unless logged_in?
      flash[:error] = "You must be logged in to access this section"
      redirect_to new_login_url # halts request cycle
    end
  end
end

Cette méthode est aussi simple que d'enregistrer le message d'erreur dans flash et de la rediriger vers le formulaire de connexion si l'utilisateur n'est pas connecté.

Dans cet exemple, nous avons ajouté un filtre à ʻApplicationController, donc tous les contrôleurs qui en héritent seront affectés. Cela signifie que vous devrez vous connecter pour chaque fonctionnalité de votre application. Bien sûr, si vous demandez une authentification sur chaque écran de l'application, vous ne pourrez pas afficher l'écran de connexion requis pour l'authentification, alors définissez la demande de connexion sur tous les contrôleurs et des actions comme celle-ci. Ne devrait pas être. La méthode skip_before_action` vous permet de sauter un filtre pour une action particulière.

class LoginsController < ApplicationController
  skip_before_action :require_login, only: [:new, :create]
end

En faisant ce qui précède, les actions "new" et "create" du "Logins Controller" peuvent toujours être authentifiées sans authentification. Vous pouvez utiliser l'option : only si vous souhaitez ignorer le filtre uniquement pour une action spécifique. Inversement, si vous ne souhaitez pas ignorer le filtre uniquement pour une action spécifique, utilisez l'option : except. Ces options peuvent également être utilisées lors de l'ajout de filtres, vous pouvez donc ajouter des filtres qui ne s'exécutent que sur l'action que vous sélectionnez en premier lieu.

8-1. Filtre ʻafter et filtre ʻaround

En plus du filtre «avant», vous pouvez également utiliser un filtre qui est exécuté après l'exécution de l'action, ou un filtre qui est exécuté à la fois avant et après l'exécution.

Le filtre "après" est similaire au filtre "avant", mais dans le cas du filtre "après", l'action a déjà été exécutée et les données de réponse qui sont sur le point d'être envoyées au client sont accessibles. Différent des filtres. Bien entendu, quelle que soit la manière dont vous écrivez le filtre «après», l'exécution de l'action ne sera pas interrompue. Cependant, veuillez noter que le filtre «après» n'est exécuté qu'après la réussite de l'action et n'est pas exécuté si une exception se produit au milieu du cycle de demande.

Si vous utilisez un filtre «autour», vous êtes obligé de faire un «yield» quelque part dans le filtre pour effectuer l'action associée. Ceci est similaire au fonctionnement du middleware Rack.

Par exemple, considérons un site Web qui a un flux de travail d'approbation pour toute modification. Les administrateurs peuvent facilement prévisualiser ces modifications et les approuver dans une transaction.

class ChangesController < ApplicationController
  around_action :wrap_in_transaction, only: :show

  private

  def wrap_in_transaction
    ActiveRecord::Base.transaction do
      begin
        yield
      ensure
        raise ActiveRecord::Rollback
      end
    end
  end
end

Notez que pour les filtres «autour», la sortie écran (rendu) est également incluse dans le travail. Surtout dans l'exemple ci-dessus, si la vue elle-même lit à partir de la base de données (en utilisant une portée, etc.), la lecture est effectuée dans la transaction et les données sont affichées dans l'aperçu.

Vous pouvez également créer votre propre réponse sans exécuter yield. Dans ce cas, aucune action n'est entreprise.

9. Protection contre la falsification des demandes

Recommended Posts

Relisez le guide des rails (vue d'ensemble du contrôleur d'action)
[Rails] Vérifiez le contenu de l'objet
Explication de l'ordre des itinéraires ferroviaires
J'ai lu la source de ArrayList que j'ai lu
J'ai lu la source d'Integer
Vérifier l'état de migration des rails
J'ai lu la source de Long
[Rails] Lire le RSS du site et renvoyer le contenu au premier plan
Lire l'implémentation de la commutation automatique multi-DB Rails 6 (ActiveRecord :: Middleware :: DatabaseSelector)
J'ai lu la source de Short
J'ai lu la source de Byte
J'ai lu la source de String
L'identité des paramètres de rails [: id]
[rails] Liste des actions définies dans Controller
[Rails] Changer le nom de l'étiquette de f.label
Rails6: Extraire l'image dans le texte d'action
Relisez le guide des rails (vue d'ensemble du contrôleur d'action)
[Rails] Supprimer le fichier de migration
Qu'est-ce que Rails Active Record?
Vérifier l'état de migration des rails
Migration des rails
[Ruby on Rails] À propos du rappel Active Record
[Rails] Méthode Active Record fréquemment utilisée même par les débutants
J'ai lu le "Guide pratique orienté objet", donc un mémorandum
[Order method] Définit l'ordre des données dans Rails
À propos du guide de démarrage officiel de Spring Framework
[Ruby on Rails] Jusqu'à l'introduction de RSpec
[Développement SPA avec Rails x Vue] Apprenez les bases de Vue.js (Vue d'ensemble de vue.js, syntaxe du modèle)