inny układ działania sign_in w urządzeniu

84

Próbuję użyć innego / niestandardowego układu o nazwie „devise” dla akcji sign_in. Znalazłem stronę na wiki devise, a drugi przykład mówi nawet, że możesz to zrobić za pomocą akcji (w tym przypadku sign_inakcji), ale nie pokazuje tego przykładu. Ktoś na IRC powiedział mi, że mogę spróbować:

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

Ale wygląda na to, że nie działa, ponieważ nadal ładuje domyślny układ aplikacji. Byłbym wdzięczny za każdą pomoc.

Jorge Israel Peña
źródło

Odpowiedzi:

96

Poniżej przedstawiono inny sposób zastosowania niestandardowego układu dla akcji.

Zgodnie z instrukcją : Tworzenie niestandardowych układów "Możesz również ustawić układ dla określonych kontrolerów Devise za pomocą wywołania zwrotnego w config / environment.rb (rails 2) lub config / application.rb (rails 3). Należy to zrobić w to_prepare wywołanie zwrotne, ponieważ jest wykonywane raz w środowisku produkcyjnym i przed każdym żądaniem w trakcie tworzenia. "

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

Zwykle rozróżnia się układ między stronami wymagającymi logowania i stronami, które nie wymagają uwierzytelniania, więc powyższe podejście działa przez większość czasu. Ale eksperymentowałem też z użyciem action_namehelpera do ustawienia układu dla określonej akcji i działało to jak urok:

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

Myślę, że jest to lepsze i zbudowane w taki sposób, aby zmienić układ w oparciu o opracowany kontroler / akcję, zamiast tworzyć pomocnika w ApplicationController.

Zeeshan
źródło
3
Nie zapomnij także zrestartować serwera za każdym razem, gdy dokonasz zmiany w jakimkolwiek pliku w folderze konfiguracyjnym, w tym przypadku config / application.rb dla Rails3 lub config / environment.rb dla Rails 2, aby zmiany odniosły skutek.
Zeeshan
Uwaga : wypróbowałem tę metodę w railsach 3.1 i znacznie spowalnia ona ładowanie zasobów z folderu zasobów. Nie wpłynie to na serwery produkcyjne, ale jeśli masz więcej niż kilka plików css / js, zauważysz to.
Gazler,
w powyższym przykładzie jest możliwe skonfigurowanie układów dla oddzielnych zasobów projektowych (np. załóżmy, że mamy dwa różne typy użytkowników urządzenia i każdy potrzebuje własnego układu)
ckarbass
Kiedy próbuję tego, pojawia się błąd, że próbuję teraz pobrać szablon z dwóch lokalizacji. Jak sprawić, by Railsy nadpisały poprzednie ustawienia Devise?
Adam Grant
Dla tych, którzy to przegapili - konfiguracja Rails 3 jest inna - zrób to w: config / application.rb (rails 3).
Stone
66

Właśnie utworzyłem app / views / layouts / devise / session.html.erb i umieściłem tam mój układ.

Josh
źródło
28
Świetne rozwiązanie! Możesz również umieścić układ w /app/views/layouts/devise.html.erb i zastosować go do wszystkich widoków urządzenia
Basti
45

Rozgryzłem to, ale zatrzymam to pytanie na wypadek, gdyby inni byli ciekawi.

To był głupi błąd. Faktem jest, że sign_inchodzi o ścieżkę, a nie działanie. Patrząc na odpowiednie źródło , widzę, że wymaganym działaniem jest newnp. Utworzenie nowej sesji Devise. Zmiana warunku powyższego kodu na:

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

Działa pięknie.

Mam nadzieję, że to pomoże komuś tam.

Jorge Israel Peña
źródło
czy nie spowoduje to zastosowania układu zarówno dla rejestracji # nowe, jak i sesji # nowych?
Ayrad,
12

Zdecydowanie najprostszym rozwiązaniem jest po prostu utworzenie układu o nazwie devise.html.haml w folderze app / views / layouts. a magia Railsów zajmie się resztą.

app/views/layouts/devise.html.haml
Jan
źródło
3
to najprostszy sposób na ustawienie układu dla urządzenia. Dzięki!
phlegx
8

Tak to zrobiłem. Chciałem mieć inny układ, jeśli użytkownik musiałby się zalogować, ale inny układ, jeśli użytkownik musiałby edytować swój profil.

Używam Rails 4.1.1

W kontrolerze aplikacji dodaj to:

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
źródło
7

Zaskoczony, że nigdzie nie widzę tej odpowiedzi, ale możesz też zrobić to:

W route.rb zmień konfigurację urządzenia, aby wyglądała mniej więcej tak:

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

Następnie w pliku app / controllers / session_controller.rb

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

Jest to szczególnie przydatne, jeśli musisz wykonać dodatkowe nadpisania logiki w którymkolwiek z kontrolerów Devise.

streetlogics
źródło
2
To jest dokładnie to, czego szukałem! Żaden z pozostałych nie działał z jakiegoś powodu: /
djGrill
1

Na wypadek, gdybyś nie wiedział, możesz również użyć rake routesdo wyświetlenia tras w aplikacji rails wraz z akcją / kontrolerem, na który mapują.

 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
źródło
Dzięki, tak naprawdę wiedziałem / wiedziałem o trasach rake'u, po prostu przez sekundę nie pomyślałem, że 'sign_in' może nie być nazwą rzeczywistej akcji, pomyślałem, że tak będzie, a potem zdałem sobie sprawę, że wszystko kręci się wokół sesji dlatego odpowiada nowej akcji.
Jorge Israel Peña,
0

Oto jedna linijka dla tych, którzy chcą, aby wszystkie działania korzystały z nowego układu:

class ApplicationController < ActionController::Base
  protect_from_forgery

  layout Proc.new { |controller| controller.devise_controller? ? 'devise' : 'application' }
end
vlad
źródło