设计中sign_in操作的不同布局


84

我正在尝试对sign_in操作使用名为“ devise”的其他/自定义布局。我在devise Wiki中找到了页面,第二个示例甚至说您可以按操作进行操作(在本例中为sign_in操作),但是没有显示执行此操作的示例。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

但它似乎仍无法正常工作,因为它仍在加载默认的应用程序布局。我将不胜感激任何帮助。

Answers:


96

为操作应用自定义布局的另一种方法如下。

根据“如何:创建自定义布局”,“您还可以使用config / environment.rb(第2列)或config / application.rb(第3列)中的回调来设置特定Devise控制器的布局。这需要在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
另外,不要忘记每次在config文件夹中的任何文件中进行更改时都重新启动服务器,在这种情况下,对于Rails3是config / application.rb,对于Rails 2是config / environment.rb,更改才能生效。
Zeeshan

请注意,我在Rails 3.1中尝试了此方法,它使从资产文件夹中加载资产的速度明显变慢。这不会影响生产服务器,但是当您拥有多个css / js文件时,您会注意到它。
Gazler

在上面的示例中,是否可以为单独的devise资源配置布局(例如,假设我们有两种不同类型的
devise

尝试此操作时,我收到一个错误,它现在正在尝试从两个位置获取模板。您如何获得Rails覆盖Devise的先前设置?
亚当·格兰特

对于那些错过它的人-Rails 3的设置是不同的-在config / application.rb(rails 3)中执行此操作。
2013年

66

我刚刚创建了app / views / layouts / devise / sessions.html.erb并将布局放在那里。


28
很好的解决方案!您还可以在/app/views/layouts/devise.html.erb中放置布局,并将其应用于您的所有devise视图
Basti 2014年

45

我想通了,但如果其他人感到好奇,我将在此保留这个问题。

这是一个愚蠢的错误。事实是sign_in道路,而不是行动。查看相关源代码,我可以看到所需的操作是new,即创建一个新的Devise Session。将我上面的代码的条件更改为:

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

做工精美。

希望可以帮助某人。


这不会同时适用于registrations#new和session#new的布局吗?
艾拉德(Ayrad)'17

12

到目前为止,最简单的解决方案是在您的app / views / layouts文件夹中创建一个名为devise.html.haml的布局。而Rails魔术负责其余的工作。

app/views/layouts/devise.html.haml

3
这是设置设计布局的最简单方法。谢谢!
phlegx

8

这就是我的方法。如果用户必须登录,我想要一个不同的布局,但是如果用户必须编辑他/她的个人资料,我想要一个不同的布局。

我正在使用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

7

很惊讶在任何地方都看不到这个答案,但是您也可以这样做:

在routes.rb中,将您的设计配置更改为如下所示:

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

然后在app / controllers / sessions_controller.rb中

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

如果您需要在任何Devise控制器中执行其他逻辑替代,则此功能特别有用。


2
这正是我在寻找的东西!没有其他人由于某种原因而工作:/
djGrill

1

万一您不知道,您还可以使用rake routes它们在Rails应用中查看路线以及它们映射到的动作/控制器。

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

谢谢,我确实了解/了解了耙路,只是我一秒钟都没有想到'sign_in'可能不是实际动作的名称,我想应该是,然后我意识到这一切都围绕着会话这就是为什么它对应于新动作。
豪尔赫·以色列·佩尼亚

0

对于那些希望所有设计动作都使用新布局的人来说,这是一条线:

class ApplicationController < ActionController::Base
  protect_from_forgery

  layout Proc.new { |controller| controller.devise_controller? ? 'devise' : 'application' }
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.