Различная компоновка для действия sign_in в разработке

Я пытаюсь использовать другой/настраиваемый макет с именем "devise" для действия sign_in. Я нашел эту страницу в викторине разработки, а второй пример даже говорит, что вы можете сделать это за действие (в данном случае, sign_in action), но это не показывает пример этого. Кто-то из IRC сказал мне, что я мог бы попробовать это:

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

Но он, похоже, не работает, поскольку он по-прежнему загружает макет приложения по умолчанию. Я был бы признателен за любую помощь.

Ответ 1

Я понял это, но я буду держать этот вопрос здесь, в случае, если другим людям будет интересно.

Это была глупая ошибка. Факт sign_in - это путь, а не действие. Если посмотреть на соответствующий источник, я вижу, что требуемое действие new, т.е. Создание нового сеанса разработки. Изменение моего кода выше:

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

Прекрасно работает.

Надеюсь, что кто-то поможет там.

Ответ 2

Другим способом применения настраиваемого макета для действия является следующее.

В соответствии с Как создать пользовательские макеты "Вы также можете установить макет для конкретных контроллеров Devise с помощью обратного вызова в config/environment.rb(rails 2) или config/application.rb(rails 3). Это нужно сделать в обратном вызове to_prepare, поскольку он выполняется один раз в процессе производства и перед каждым запросом в разработке".

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

Обычно различие между макетами выполняется между страницами за входами и страницами, для которых не требуется аутентификация, поэтому подобный подход работает большую часть времени. Но я также экспериментировал с использованием помощника action_name для установки макета для конкретного действия, и он работал как шарм:

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

Я думаю, что это лучше и встроено в способ изменения макета, основанного на разработке контроллера/действия, вместо создания помощника в ApplicationController.

Ответ 3

Я только что создал приложение /views/layouts/devise/sessions.html.erb и разместил там свой макет.

Ответ 4

Вот как я это сделал. Мне нужен другой макет, если пользователь должен был войти, но другой макет, если пользователь должен был отредактировать свой профиль.

Я использую Rails 4.1.1

В контроллере приложения добавьте следующее:

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

Ответ 5

Самое простое решение - просто создать макет под названием devise.html.haml в папке app/views/layouts. и магия Rails заботится обо всем остальном.

app/views/layouts/devise.html.haml

Ответ 6

Удивленный, чтобы не видеть этот ответ нигде, но вы также можете это сделать:

В routes.rb измените конфигурацию своего проекта, чтобы выглядеть примерно так:

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

Затем в app/controller/sessions_controller.rb

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

Это особенно полезно, если вам нужно выполнить дополнительные логические переопределения в любом из контроллеров Devise.

Ответ 7

Просто вы не знаете, вы также можете использовать rake routes, чтобы увидеть маршруты в своем приложении rails вместе с файлом action/controller, к которому они привязаны.

 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"}

Ответ 8

Здесь один лайнер для тех, кто хочет, чтобы все разрабатывали действия для использования нового макета:

class ApplicationController < ActionController::Base
  protect_from_forgery

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