disposition différente pour l'action sign_in dans la devise

84

J'essaye d'utiliser une mise en page différente / personnalisée nommée "devise" pour l'action sign_in. J'ai trouvé cette page dans le wiki de conception, et le deuxième exemple dit même que vous pouvez le faire par action (dans ce cas, sign_inaction), mais il ne montre aucun exemple de le faire. Quelqu'un sur IRC m'a dit que je pouvais essayer ceci:

class ApplicationController < ActionController::Base
  protect_from_forgery

  layout :layout_by_resource

  def layout_by_resource
    if devise_controller? && resource_name == :user && action_name == 'sign_in'
      "devise"
    else
      "application"
    end
  end
end

Mais cela ne semble pas fonctionner car il charge toujours la mise en page par défaut de l'application. J'apprécierais toute aide.

Jorge Israel Peña
la source

Réponses:

96

Une autre façon d'appliquer une mise en page personnalisée pour une action est la suivante.

Selon Comment: Créer des dispositions personnalisées "Vous pouvez également définir la disposition pour des contrôleurs Devise spécifiques à l'aide d'un rappel dans config / environment.rb (rails 2) ou config / application.rb (rails 3). Cela doit être fait dans un to_prepare callback car il est exécuté une fois en production et avant chaque requête en développement. "

config.to_prepare do
    Devise::SessionsController.layout "devise"
    Devise::RegistrationsController.layout proc{ |controller| user_signed_in? ? "application"   : "devise" }
    Devise::ConfirmationsController.layout "devise"
    Devise::UnlocksController.layout "devise"            
    Devise::PasswordsController.layout "devise"        
end

Habituellement, une distinction de mise en page est faite entre les pages derrière la connexion et les pages qui ne nécessitent pas d'authentification, de sorte que l'approche ci-dessus fonctionne la plupart du temps. Mais j'ai également expérimenté l'utilisation de action_namehelper pour définir une mise en page pour une action particulière et cela a fonctionné comme un charme:

config.to_prepare do
    Devise::SessionsController.layout proc{ |controller| action_name == 'new' ? "devise"   : "application" }
end

Je pense que c'est la meilleure manière intégrée de changer la mise en page basée sur le contrôleur / l'action de conception au lieu de créer un assistant dans ApplicationController.

Zeeshan
la source
3
N'oubliez pas non plus de redémarrer le serveur chaque fois que vous apportez une modification à un fichier du dossier config, dans ce cas config / application.rb pour Rails3 ou config / environment.rb pour Rails 2, pour que les modifications prennent effet.
Zeeshan
Attention, j'ai essayé cette méthode dans rails 3.1 et cela ralentit considérablement le chargement des actifs depuis le dossier des actifs. Cela n'affectera pas les serveurs de production, mais lorsque vous avez plus de quelques fichiers css / js, vous le remarquerez.
Gazler
dans l'exemple ci-dessus, est-il possible de configurer des mises en page pour des ressources de périphérique distinctes (par exemple, supposons que nous avons deux types différents d'utilisateurs de
périphérique
Lorsque j'essaye ceci, j'obtiens une erreur indiquant qu'il essaie maintenant d'obtenir un modèle à partir de deux emplacements. Comment faire pour que Rails remplace les paramètres précédents de Devise?
Adam Grant
Pour ceux qui l'ont manqué - la configuration de Rails 3 est différente - faites ceci dans: config / application.rb (rails 3).
Stone
66

Je viens de créer app / views / layouts / devise / sessions.html.erb et y mettre ma mise en page.

Josh
la source
28
Excellente solution! Vous pouvez également mettre une mise en page dans /app/views/layouts/devise.html.erb et l'appliquer à toutes vos vues de
devise
45

Je l'ai compris, mais je vais garder cette question ici au cas où d'autres personnes seraient curieuses.

C'était une erreur stupide. Le fait est que sign_inc'est le chemin, pas l'action. En regardant la source pertinente , je peux voir que l'action requise est new, c'est-à-dire, la création d'une nouvelle Devise Session. Changer le conditionnel de mon code ci-dessus en:

if devise_controller? && resource_name == :user && action_name == 'new'

Fonctionne à merveille.

J'espère que cela aide quelqu'un là-bas.

Jorge Israel Peña
la source
cela n'appliquerait-il pas la mise en page pour les inscriptions # new et les sessions # new?
Ayrad
12

La solution de loin la plus simple consiste simplement à créer une mise en page appelée devise.html.haml dans votre dossier app / views / layouts. et la magie Rails s'occupe du reste.

app/views/layouts/devise.html.haml
John
la source
3
c'est le moyen le plus simple de définir une mise en page pour la conception. Merci!
phlegx
8

Voilà comment je l'ai fait. Je voulais une mise en page différente si l'utilisateur devait se connecter, mais une mise en page différente si l'utilisateur devait modifier son profil.

J'utilise Rails 4.1.1

Dans le contrôleur d'application, ajoutez ceci:

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?

  layout :layout_by_resource

  # Define the permitted parameters for Devise.
  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:firstname, :lastname, :email, :password, :password_confirmation)}
    devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:avatar, :firstname, :lastname, :email, :password, :password_confirmation, :current_password) }
  end

  def layout_by_resource
    if devise_controller? and user_signed_in?
      'dashboard'
    else
      'application'
    end
  end
end
Sankalp Singha
la source
7

Surpris de ne voir cette réponse nulle part, mais vous pouvez aussi le faire:

Dans routes.rb, modifiez la configuration de votre appareil pour ressembler à ceci:

  devise_for :users, controllers: {
    sessions: 'sessions'
  }

Puis dans app / controllers / sessions_controller.rb

class SessionsController < Devise::SessionsController
  layout 'devise', only: [:new]
end

Ceci est particulièrement utile si vous devez effectuer des remplacements de logique supplémentaires dans l'un des contrôleurs Devise.

streetlogics
la source
2
C'est exactement ce que je cherchais! Aucun des autres n'a fonctionné pour une raison quelconque: /
djGrill
1

Juste au cas où vous ne le saviez pas, vous pouvez également utiliser rake routespour voir les itinéraires dans votre application de rails avec l'action / le contrôleur auquel ils sont mappés.

 new_user_registration GET    /accounts/sign_up(.:format)       {:action=>"new", :controller=>"devise/registrations"}
edit_user_registration GET    /accounts/edit(.:format)          {:action=>"edit", :controller=>"devise/registrations"}
                       PUT    /accounts(.:format)               {:action=>"update", :controller=>"devise/registrations"}
                       DELETE /accounts(.:format)               {:action=>"destroy", :controller=>"devise/registrations"}
Dty
la source
Merci, en fait, je connaissais / connaissais les routes de rake, je n'avais tout simplement pas pensé une seconde que 'sign_in' pourrait ne pas être le nom de l'action réelle, j'ai pensé que ce serait le cas, puis j'ai réalisé que tout tournait autour des sessions c'est pourquoi il correspond à la nouvelle action.
Jorge Israel Peña
0

Voici une ligne unique pour ceux qui souhaitent que toutes les actions de conception utilisent une nouvelle mise en page:

class ApplicationController < ActionController::Base
  protect_from_forgery

  layout Proc.new { |controller| controller.devise_controller? ? 'devise' : 'application' }
end
Vlad
la source