anderes Layout für die Aktion sign_in in devise

84

Ich versuche, ein anderes / benutzerdefiniertes Layout mit dem Namen "devise" für die Aktion "sign_in" zu verwenden. Ich habe diese Seite im Entwickler-Wiki gefunden, und das zweite Beispiel besagt sogar, dass Sie es pro Aktion (in diesem Fall sign_inAktion) ausführen können, aber es zeigt kein Beispiel dafür. Jemand im IRC sagte mir, ich könnte das versuchen:

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

Es scheint jedoch nicht zu funktionieren, da immer noch das Standardanwendungslayout geladen wird. Ich würde mich über jede Hilfe freuen.

Jorge Israel Peña
quelle

Antworten:

95

Eine andere Möglichkeit, ein benutzerdefiniertes Layout für eine Aktion anzuwenden, ist die folgende.

Nach wie: Erstellen von benutzerdefinierten Layouts „Sie auch das Layout für spezifische Controller Devise einstellen können ein Rückruf in config / environment.rb (Rails 2) oder config / application.rb (Schienen 3) Mit diesem Bedarf in einem getan werden. to_prepare-Rückruf, da er einmal in der Produktion und vor jeder Anforderung in der Entwicklung ausgeführt wird. "

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

Normalerweise wird zwischen Seiten hinter der Anmeldung und Seiten, für die keine Authentifizierung erforderlich ist, im Layout unterschieden, sodass der oben beschriebene Ansatz die meiste Zeit funktioniert. Ich habe aber auch mit dem action_nameHelfer experimentiert , um ein Layout für eine bestimmte Aktion festzulegen, und es hat wie ein Zauber funktioniert:

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

Ich denke, dies ist die bessere und eingebaute Methode, um das Layout basierend auf dem geplanten Controller / der Aktion zu ändern, anstatt einen Helfer in ApplicationController zu erstellen.

Zeeshan
quelle
3
Vergessen Sie auch nicht, den Server jedes Mal neu zu starten, wenn Sie Änderungen an einer Datei im Konfigurationsordner vornehmen, in diesem Fall config / application.rb für Rails3 oder config / environment.rb für Rails 2, damit die Änderungen wirksam werden.
Zeeshan
Beachten Sie, dass ich diese Methode in Rails 3.1 ausprobiert habe und das Laden von Assets aus dem Assets-Ordner dadurch erheblich verlangsamt wird. Dies wirkt sich nicht auf Produktionsserver aus. Wenn Sie jedoch mehr als ein paar CSS / JS-Dateien haben, werden Sie dies bemerken.
Gazler
Im obigen Beispiel ist es möglich, Layouts für separate Entwicklerressourcen zu konfigurieren (z. B. tun wir so, als hätten wir zwei verschiedene Arten von Benutzerbenutzern und jeder benötigt sein eigenes Layout)
ckarbass
Wenn ich dies versuche, wird die Fehlermeldung angezeigt, dass jetzt versucht wird, eine Vorlage von zwei Speicherorten abzurufen. Wie bringt man Rails dazu, die vorherigen Einstellungen von Devise zu überschreiben?
Adam Grant
Für diejenigen, die es verpasst haben - Rails 3-Setup ist anders - tun Sie dies in: config / application.rb (Rails 3).
Stein
65

Ich habe gerade app / views / layouts / devise / session.html.erb erstellt und mein Layout dort eingefügt.

Josh
quelle
28
Tolle Lösung! Sie können auch ein Layout in /app/views/layouts/devise.html.erb einfügen und es auf alle Ihre Entwurfsansichten anwenden lassen
Basti
45

Ich habe es herausgefunden, aber ich werde diese Frage hier behalten, falls andere neugierig sind.

Es war ein dummer Fehler. Tatsache ist sign_inder Weg, nicht die Handlung. Wenn ich mir die relevante Quelle ansehe , kann ich sehen, dass die erforderliche Aktion darin besteht new, eine neue Gerätesitzung zu erstellen . Ändern der Bedingung meines obigen Codes in:

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

Funktioniert wunderbar.

Hoffe das hilft jemandem da draußen.

Jorge Israel Peña
quelle
Würde dies nicht das Layout für beide Registrierungen # neu und Sitzungen # neu anwenden?
Ayrad
10

Die mit Abstand einfachste Lösung besteht darin, einfach ein Layout mit dem Namen devise.html.haml in Ihrem Ordner app / views / layouts zu erstellen. und die Rails-Magie kümmert sich um den Rest.

app/views/layouts/devise.html.haml
John
quelle
2
Dies ist der einfachste Weg, um ein Layout für die Entwicklung festzulegen. Vielen Dank!
Phlegx
8

So habe ich es gemacht. Ich wollte ein anderes Layout, wenn sich der Benutzer anmelden musste, aber ein anderes Layout, wenn der Benutzer sein Profil bearbeiten musste.

Ich benutze Rails 4.1.1

Fügen Sie im Anwendungscontroller Folgendes hinzu:

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
quelle
7

Überrascht, diese Antwort nirgendwo zu sehen, aber Sie können auch Folgendes tun:

Ändern Sie in route.rb Ihre Gerätekonfiguration so, dass sie ungefähr so ​​aussieht:

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

Dann in app / controller / session_controller.rb

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

Dies ist besonders nützlich, wenn Sie zusätzliche Logiküberschreibungen in einem der Devise-Controller durchführen müssen.

Straßenlogik
quelle
2
Genau das habe ich gesucht! Keiner der anderen arbeitete aus irgendeinem Grund: /
djGrill
1

Nur für den Fall, dass Sie es nicht wussten, können Sie auch rake routesdie Routen in Ihrer Rails-App zusammen mit der Aktion / Steuerung anzeigen, der sie zugeordnet sind.

 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
quelle
Vielen Dank, ich wusste / wusste tatsächlich über Rake-Routen Bescheid. Ich hatte nur keine Sekunde lang gedacht, dass 'sign_in' möglicherweise nicht der Name der eigentlichen Aktion ist. Ich dachte mir, dass dies der Fall sein würde. Dann wurde mir klar, dass sich alles um Sitzungen dreht Deshalb entspricht es der neuen Aktion.
Jorge Israel Peña
0

Hier ist ein Einzeiler für diejenigen, die möchten, dass alle erarbeiteten Aktionen ein neues Layout verwenden:

class ApplicationController < ActionController::Base
  protect_from_forgery

  layout Proc.new { |controller| controller.devise_controller? ? 'devise' : 'application' }
end
vlad
quelle