-
Notifications
You must be signed in to change notification settings - Fork 5.5k
How To: Create custom layouts
If you simply want to use a custom layout across every Devise views, you can simply create a layout and name it devise.html.erb
.
If you would like be more specific about how your custom layouts for Devise, you have two main options:
- Define layouts in the Controller
- Define layouts in the ApplicationController
- Define layouts in config (config/environment.rb for rails 2, config/application.rb in rails 3)
The laziest method is to add a layout definition to the top of the controller and limit it to the needed action:
class User::RegistrationsController < Devise::RegistrationsController
layout 'dashboard', only: [:edit]
def edit
super
end
end
By using the devise_controller?
helper you can determine when a Devise controller is active and respond accordingly. To have Devise use a separate layout to the rest of your application, you could do something like this:
class ApplicationController < ActionController::Base
layout :layout_by_resource
protected
def layout_by_resource
if devise_controller?
"layout_name_for_devise"
else
"application"
end
end
end
You can build upon this to set a layout per role (or even per action). Below, resource_name
is used to detect when Devise is handling an admin.
layout :layout_by_resource
protected
def layout_by_resource
if devise_controller? && resource_name == :admin
"layout_name_for_devise_admin"
else
"application"
end
end
Here is an example of a layout by action
layout :layout_by_resource
protected
def layout_by_resource
if devise_controller? && resource_name == :user && action_name == "new"
"layout_name_for_devise"
else
"application"
end
end
Note that if you have a devise.html.erb
layout, it will take precedence over a layout specified in ApplicationController.
You can also set the layout for specific Devise controllers using a callback in config/environment.rb (rails 2) or config/application.rb (rails 3). This needs to be done in a to_prepare
callback because it's executed once in production and before each request in development.
This allows for layouts to be specified on a per-controller basis. If, for example, you want a specific layout assigned to Devise::SessionsController
views:
config.to_prepare do
Devise::SessionsController.layout "layout_for_sessions_controller"
end
Or to configure the email layout:
config.to_prepare do
Devise::Mailer.layout "email" # email.haml or email.erb
end
If you want the same layout for all Devise views, except for when the user is editing its data, you could have something like this:
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
If you prefer to put all config stuff in devise.rb config file:
# append to end of config/initializers/devise.rb
Rails.application.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