Rails: Multiple layouts with Devise - ruby-on-rails

How can I have a completely different layout depending on wether a user is logged in or not?

Follow the instructions at
https://github.com/plataformatec/devise/wiki/How-To%3a-Create-custom-layouts
and make the check be if the user is logged in, which for devise means checking
user_signed_in?, which is a devise helper.
Specifically:
class ApplicationController < ActionController::Base
layout :layout_by_resource
protected
def layout_by_resource
if user_signed_in?
"special_layout_name_for_logged_in"
else
"application"
end
end
end
and put the special_layout_for_logged_in.html.erb view file in the layouts directory.

Related

how to use different layout for different pages in ruby on rails?

i know application.html.erb is the default for every page .i want to use a different layout when user login .i mean the dashboard after login should be of different layout rather than the default one(application.html.erb).
Create new layout eg app/views/layouts/dunno.html.erb. Use in controller
class DashboardController < ApplicationController
layout 'dunno'
end
or per action
class DashboardController < ApplicationController
def index
render layout: 'dunno'
end
end
see docs for details
You can do this in application controller, add this code, I am assuming that you are using devise
layout :layout_by_resource
def layout_by_resource
user_signed_in? ? "my_custom_layout" : "application"
end
In your application_controller.rb file do this, hope it helps.
layout :set_layout
def set_layout
if current_user
'dashboard_layout'
else
'default_layout'
end
end
Details about layouts can be found here.
Using a different layout in the action render call
If most of your actions use the same layout, it makes perfect sense to
define a controller-wide layout as described above. Sometimes you'll
have exceptions where one action wants to use a different layout than
the rest of the controller. You can do this by passing a :layout
option to the render call. For example:
class WeblogController < ActionController::Base
layout "weblog_standard"
def help
render action: "help", layout: "help"
end
end
This will override the controller-wide “weblog_standard” layout, and will render the help
action with the “help” layout instead.
If you are using devise gem, and your goal is to use another layout within devise controllers, have a look at their docs
i wanted two different layouts before signin and after signin,so i have implemented using below code where application_controller changes the layout if user is signed_in else uses different layout....
if you are using devise ,dont forget to add layouts in views/layouts
in application_controller.rb
layout :layout_by_resource
def layout_by_resource
unless user_signed_in?
Rails.logger.info "===========Setting layout as views/layouts/auth.html.erb"
'auth'
else
Rails.logger.info "===========Setting layout as views/layouts/blue.html.erb"
'basic'
end
end

How to configure Devise+Cancan correctly for guest users

In a Rails 3.2 app I'm using Devise + CanCan. The app previously restricted access to only logged in users. I'm in the process of adding a Guest user/ability that will be able to read certain sections of the site.
I'm having trouble understanding the "correct" way to set this up, specifically what combination of before_filter :authenticate! and load_and_authorize_resource is needed in controllers.
While working on this I've stripped the ability class to a minimum.
#Ability.rb
class Ability
include CanCan::Ability
def initialize(user_or_admin)
user_or_admin ||= User.new
can :manage, :all
end
end
In a model-less/ static page Home controller
#home_controller.rb
class HomeController < ApplicationController
load_and_authorize_resource
def index
...some stuff
end
end
and
#application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate!
...more stuff
end
With this set up, un-logged-in users are redirected to Devise sign in page.
If I remove before_filter :authenticate! from the application controller I get an error uninitialized constant Home from activesupport-3.2.11/lib/active_support/inflector/methods.rb
If I remove load_and_authorize_resource from the home controller, this error goes away.
This is ok with my simplified testing Ability class, but as I start adding roles and abilities back in I will need to have CanCan handling the Home controller, i.e., will need load_and_authorize_resource to be called.
Can anyone help me understand why this error occurs when before_filter :authenticate! is removed, and point me towards any info that explain the "correct" way to set up Devise+Cancan for guest users. The info I've found thus far only explains how to set up the Ability class, not how to configure Devise.
The problem is that there is no resource to authorize. Therefore, you need only call authorize_resource not load_and_authorize_resource. See authorizing controller actions in the cancan documentation for further information.
Update: You must also specify the class as false: authorize_resource class: false.
Then your home controller will look like this:
class HomeController < ActionController::Base
authorize_resource class: false
def show
# automatically calls authorize!(:show, :home)
end
end
This information is in the Non-RESTful controllers section. Sorry about that.

Can't get skip_before_filter to work with ActiveAdmin in Rails

I am using the devise gem for authentication and have the following before_filter in my ApplicationController:
before_filter :require_login
def require_login
unless user_signed_in? || params[:controller] == 'devise/sessions'
flash[:error] = "You must be logged in to access that page."
redirect_to new_user_session_path
end
end
I have recently implemented the ActiveAdmin gem and am trying to get skip_before_filter to work for ActiveAdmin, so that I can access ActiveAdmin. I have attempted the methods outlined in this post, adding the following to config/initializers/active_admin.rb:
config.skip_before_filter :require_login
and also adding the following to one of my admin model files, listing.rb:
ActiveAdmin.register Listing do
controller do
skip_before_filter :require_login
end
end
but it doesn't seem to work, even after restarting the server and browser.
What am I doing wrong?
So two things:
First: I think you're using Devise inefficiently. Instead of a custom login method on application_controller, you should:
class ApplicationController
before_filter :authenticate_user!
end
That's it -- everything else works.
Second: Active Admin uses a different user class -- the "admin_user" (rather than "user"). By default, you'll use the following credentials:
email: admin#example.com
password: password

Rails: Devise: redirect after sign in by role

Is it possible to redirect users to different pages (based on role) after signing in with Devise? It only seems to redirect to the root :to => ... page defined in routes.rb
By default Devise does route to root after it's actions. There is a nice article about overriding these actions on the Devise Wiki, https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in
Or you can go even farther by setting stored_locations_for(resource) to nil, and then have different redirects for each action, ie: after_sign_up_path(resource), after_sign_in_path(resource) and so on.
You can simply add this method to your application controller:
def after_sign_in_path_for(resource)
user_path(current_user) # your path
end
Devise has a helper method after_sign_in_path_for which can be used to override the default Devise route to root after login/sign-in.
To implement a redirect to another path after login, simply add this method to your application controller.
#class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
users_path
end
Where users_path is the path that you want it to redirect to, User is the model name that corresponds to the model for Devise.
Note: If you used Admin as your model name for Devise, then it will be
#class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
admins_path
end
Also, if you generated controllers for Devise, then you can define this in the sessions controller, say, your Devise model is Admin, you can define this in the app/controllers/admins/sessions_controller.rb file to route to the dashboard_index_path:
# app/controllers/admins/sessions_controller.rb'
def after_sign_in_path_for(resource)
dashboard_index_path
end
And in the registrations controller - app/controllers/admins/registrations_controller.rb file:
# app/controllers/admins/registrations_controller.rb
def after_sign_up_path_for(resource)
dashboard_index_path
end
That's all.
I hope this helps
You can use the below code in the application controller or any controller where you need to do the operation:
def after_sign_in_path_for(resource)
users_path
end
https://github.com/heartcombo/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in,-sign-up,-or-sign-out
I used example 1:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
protected
def after_sign_in_path_for(resource)
current_user.is_a?(Admin) ? admin_tests_path : (stored_location_for(resource) || root_path)
end
end
To expand on the answer provided by #Asnad Atta
Here is what I ended up using.
def after_sign_in_path_for(resource)
if current_user.role == 'admin'
start_path
else
news_path
end
end
I wanted everyone who logs in to first be pushed to a News page.
After the initial login the Home on the Navbar goes to the start_path (just what I call it in my app). The start_path is also in my root to:
This wonderful after_sign_in_path_for(resource) over rides the root to: path ONLY on the initial Login.
This is exactly what I wanted.
I hope this can help save someone some time.
Scott
Here's what I believe is the answer you are looking for from the devise wiki:
How To: Change the default sign_in and sign_out routes

Devise Layouts for SignedIn & Signed Out resources

My App has two UI states:
- Signed IN
- Signed Out
I've been using the following to determine which app/view/layout to use based on if the user is signed in or out with Devise:
# Devise, way of using a different Layout for all the devise/non-signed in Views
layout :layout_by_resource
def layout_by_resource
if devise_controller?
"application_unauthorized"
else
"application"
end
end
The problem is once your signed in it uses the wrong layout? ideas?
I only want to use "application_unauthorized" if it's devise & the user is not signed in.
Actually you should use the user_signed_in? method to check if the user is signed in. I noticed that current_user? might return true even if the user is currently not signed in.
So your code would look something like this:
layout :layout_by_resource
def layout_by_resource
if user_signed_in?
"application"
else
"application_unauthorized"
end
end
Personally I would check using if current_user? rather than devise_controller?

Resources