Les filtres sont des méthodes exécutées "avant", "après" ou "autour" d'une action de contrôleur. Ils sont hérités, donc si vous en définissez dans votre ApplicationController ils seront exécutés pour chaque requête reçue par votre application.
Avant filtre
Avant que les filtres ne soient exécutés avant l'action du contrôleur et peuvent arrêter la demande (et / ou la redirection). Une utilisation courante consiste à vérifier si un utilisateur est connecté:
class ApplicationController < ActionController::Base before_action :authenticate_user!
def authenticate_user!
redirect_to some_path unless user_signed_in? end
end
Avant que les filtres ne soient exécutés sur les requêtes avant que la requête n'arrive à l'action du contrôleur. Il peut renvoyer une réponse elle-même et contourner complètement l'action.
D'autres utilisations courantes des filtres avant sont la validation de l'authentification d'un utilisateur avant de lui accorder l'accès à l'action désignée pour traiter leur demande. Je les ai également vus utilisés pour charger une ressource de la base de données, vérifier les
autorisations sur une ressource ou gérer les redirections dans d'autres circonstances. Après filtre
Après les filtres sont similaires à ceux "avant", mais comme ils sont exécutés après l'exécution de l'action, ils ont accès à l'objet de réponse qui est sur le point d'être envoyé. Donc, en bref, après l'exécution des filtres une fois l'action terminée. Il peut modifier la réponse. La plupart du temps, si quelque chose est fait dans un filtre après, cela peut être fait dans l'action elle-même, mais s'il y a une logique à exécuter après avoir exécuté un ensemble d'actions, alors un filtre après est un bon endroit il.
Généralement, j'ai vu après et autour des filtres utilisés pour la journalisation. Filtre autour
Autour des filtres peuvent avoir la logique avant et après l'action en cours d'exécution. Il cède simplement à l'action dans n'importe quel endroit est nécessaire. Notez qu'il n'a pas besoin de céder à l'action et peut s'exécuter sans le faire comme un filtre avant.
Les filtres Around sont chargés d’exécuter les actions associées, tout comme les middlewares Rack fonctionnent.
Les callbacks entourent l'exécution des actions. Vous pouvez écrire un rappel autour de deux styles différents. Dans le premier, le rappel est un morceau de code unique. Ce code est appelé avant l'exécution de l'action. Si le code de rappel appelle le rendement, l'action est exécutée. Une fois l'action terminée, le code de rappel continue à s'exécuter. Ainsi, le code avant le rendement est comme un rappel d'action avant et le code après le rendement est le rappel après action. Si le code de rappel n'appelle jamais le rendement. L'action n'est pas exécutée, c'est la même chose que d'avoir un retour de rappel d'action avant false.
Voici un exemple du filtre autour: around_filter :catch_exceptions private def catch_exceptions begin yield rescue Exception => e
logger.debug "Caught exception! #{e.message}" end
end
Cela interceptera toute exception et mettra le message dans votre journal. Vous pouvez utiliser des filtres pour la gestion des exceptions, la configuration et le démontage, ainsi que de nombreux autres cas.
Seulement et sauf
Tous les filtres peuvent être appliqués à des actions spécifiques, en utilisant :only and :except : class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update]
# ... controller actions
# Define your filters as controller private methods private def set_product @product = Product.find(params[:id]) end end Filtre à sauter
Tous les filtres (ceux hérités aussi) peuvent également être ignorés pour certaines actions spécifiques:
class ApplicationController < ActionController::Base before_action :authenticate_user!
def authenticate_user!
redirect_to some_path unless user_signed_in? end
end
class HomeController < ApplicationController
skip_before_action :authenticate_user!, only: [:index]
def index end end
Comme ils sont hérités, les filtres peuvent également être définis dans un contrôleur "parent" d' namespace . Dites par exemple que vous avez un espace de noms admin et que vous voulez bien sûr que seuls les utilisateurs administrateurs puissent y accéder. Vous pourriez faire quelque chose comme ça:
# config/routes.rb namespace :admin do resources :products end
# app/controllers/admin_controller.rb
class AdminController < ApplicationController before_action :authenticate_admin_user!
private
def authenticate_admin_user!
redirect_to root_path unless current_user.admin? end
end
# app/controllers/admin/products_controller.rb class Admin::ProductsController < AdminController
# This controller will inherit :authenticate_admin_user! filter end
Attention, dans Rails 4.x, vous pouvez utiliser before_filter avec before_action , mais before_filter est actuellement obsolète dans Rails 5.0.0 et sera supprimé dans 5.1 .
Générer un contrôleur
Rails fournit beaucoup de générateurs, pour les contrôleurs aussi bien sûr.
Vous pouvez générer un nouveau contrôleur en exécutant cette commande dans le dossier de votre application.
rails generate controller NAME [action action] [options]
Remarque: Vous pouvez également utiliser des rails g alias pour appeler des rails generate
rails generate controller products index show
Cela va créer le contrôleur dans app/controllers/products_controller.rb , avec les deux actions que vous avez spécifiées
class ProductsController < ApplicationController def index
end
def show end end
Il créera également un dossier de products dans app/views/ , contenant les deux modèles pour les actions de votre contrôleur (c.-à-d index.html.erb show.html.erb et show.html.erb , notez que
l’extension peut varier selon votre moteur de template, donc si vous utilise slim , par exemple, le générateur va créer index.html.slim et show.html.slim )
De plus, si vous avez spécifié des actions, elles seront également ajoutées à votre fichier de routes .
# config/routes.rb get 'products/show' get 'products/index'
Rails crée un fichier d'aide dans app/helpers/products_helper.rb , ainsi que les fichiers de
ressources dans app/assets/javascripts/products.js et app/assets/stylesheets/products.css . En ce qui concerne les vues, le générateur modifie ce comportement en fonction de ce qui est spécifié dans votre Gemfile : par exemple, si vous utilisez Coffeescript et Sass dans votre application, le générateur de contrôleur Coffeescript plutôt products.coffee et products.sass .
Enfin, Rails génère des fichiers de test pour votre contrôleur, votre assistant et vos vues.
Si vous ne voulez pas que l'un de ces éléments soit créé, vous pouvez demander à Rails de les ignorer.
--no- ou --skip , comme ceci:
rails generate controller products index show --no-assets --no-helper
Et le générateur ignorera les assets et les helper
Si vous devez créer un contrôleur pour un namespace spécifique, ajoutez-le devant NAME : rails generate controller admin/products
Cela va créer votre contrôleur dans app/controllers/admin/products_controller.rb Rails peut également générer un contrôleur RESTful complet pour vous:
rails generate scaffold_controller MODEL_NAME # available from Rails 4 rails generate scaffold_controller Product
Sauver ActiveRecord :: RecordNotFound avec redirect_to
Vous pouvez récupérer une exception RecordNotFound avec une redirection au lieu d'afficher une page d'erreur:
class ApplicationController < ActionController::Base
# your other stuff
rescue_from ActiveRecord::RecordNotFound do |exception|
redirect_to root_path, 404, alert: I18n.t("errors.record_not_found") end
end
Chapitre 4: ActionMailer
Introduction
Action Mailer vous permet d'envoyer des e-mails depuis votre application à l'aide de classes et de vues de courrier. Les publiposteurs fonctionnent de manière très similaire aux contrôleurs. Ils héritent d'ActionMailer :: Base et vivent dans les applications / les courriers, et ils ont des vues associées qui apparaissent dans les applications / vues.
Remarques
Il est conseillé de traiter l'envoi de courrier électronique de manière asynchrone afin de ne pas bloquer votre serveur Web. Cela peut être fait par le biais de divers services tels que delayed_job .