currently with devise & rails 3 there is a one page user edit page: /users/edit
I would like to split that out into sections for a better UI, something like:
/account/settings
/account/password
/account/notices
/account/disable
Also, I'd like to require the user to enter their current password when a user wants to change their password.
With devise, to make this happen, does this require a new controller, or can this all be handled with routes?
Also, currently, the edit page lives here: app/views/devise/registrations
Do you recommend adding these pages there? Or in /app/views/users ?
Thanks
You have multiple options here. I would go with the first option as it seems to more naturally fit what you are trying to do.
Override devise's registrations controller by inheriting from it, and update the corresponding views and routes. Here is what devise's site says about this:
Configuring controllers
If the customization at the views
level is not enough, you can customize
each controller by following these
steps:
1) Create your custom controller, for
example a Admins::SessionsController:
class Admins::SessionsController < Devise::SessionsController
end
2) Tell the router to use this
controller:
devise_for :admins, :controllers => { :sessions => "admins/sessions" }
3) And since we changed the
controller, it won’t use the
"devise/sessions" views, so remember
to copy "devise/sessions" to
"admin/sessions".
Remember that Devise uses flash
messages to let users know if sign in
was successful or failed. Devise
expects your application to call
"flash[:notice]" and "flash[:alert]"
as appropriate.
Use the User controller and add actions there with corresponding views (not my choice)
Related
I want to customize devise session & registration controller.
I am even adding Active Admin to the app.
What is the correct process to override these controllers?
& I want to use both the controllers(customized as well as original). Is it possible?
Active Admin - original devise controllers
normal user - customized controllers.
When we are creating customized controllers, does same name cause any problem?
Thanks,
Avi
If you want to add a admin role to your devise, have a look at https://github.com/plataformatec/devise/wiki/How-To:-Add-an-Admin-role.
If you want to customise your current devise You can customise the devise views by copying the views from the gem into your application and then modifying them. The below line would copy the views into your application
rails generate devise:views
If you want to modify controllers, Follow below steps
You would have to create your own customise controller say Admins::SessionsController
class Admins::SessionsController < Devise::SessionsController
end
Note that in the above example, the controller needs to be created in the app/controller/admins/ directory.
Now tell the router to use this controller
devise_for :admins, :controllers => { :sessions => "admins/sessions" }
And since we changed the controller, it won't use the "devise/sessions" views, so remember to copy "devise/sessions" to "admins/sessions".
There is a rail cast video for active admin at http://railscasts.com/episodes/284-active-admin
I'm pondering over what would be the best solution for the following scenario:
We have a basic website which everybody can navigate without sign up/sign in. The controllers and views live under app/controllers and app/views/model_name.
When the user signs up and logs in (with devise) she should be redirected to a different controller under app/users/ and correspondingly to different views under app/views/users/.
I know, I could render different partials based on signed_in? from my views and I could also redirect from the default controller to the controller nested under the user directory, but I feel there must a more general approach.
I'm wondering if it could be done with routing alone (and of course having the directory structure with the different controller/view pairs in place).
Example:
app/
controllers/
albums_controller.rb
users/
albums_controller.rb
views/
albums/
index.rb
users/
albums/
index.rb
Edit: I rewrote this post being a little bit more specific and got pointed towards the solution which consisted in overriding after_sign_in_path_for.
I can think of two ways:
Combine a redirection with a custom constraint
Create a sub-class of ApplicationController:
class SignedOutApplicationController < ApplicationController
before_action :redirect_if_signed_in
...
end
and make it the sub-class for all of the non-user controllers. For symmetry I would create a SignedInController
I have a Rails 4 application using Devise for authentication.
In addition to the standard Devise login page, I want to have partner login pages that basically look and function the same way, but have a unique URL, like:
http://example.com/partner1
What is the best way to do this? I'm not sure how the routes file should look. And is using FriendlyID a good idea as well?
I have a PartnerPage model in the database which contains a "link" field, which is where the admin will enter the link/partner code.
Creating a custom route to the signup form is pretty straight forward:
get '/partner1', to: 'devise/sessions#new'
However if you want to have a customized login screen a good solution is to subclass Devise::SessionsController.
# app/controllers/partner1/sessions_controller.rb
class Partner1::SessionsController < Devise::SessionsController; end
and in your routes:
get '/partner1', to: 'partner1/sessions#new'
This will render app/veiws/partner1/sessions/new.html.erb.
I have an Accounts model set up with Devise. Devise uses a few attributes (such as email, password etc.) but I have a few other attributes that I made. On sign up, I'd like to set them up in a way.
How can I extend the registration controller? I understand that I need to actually create a new controller like this:
class AccountsController < Devise::RegistrationController
def create
super
end
end
Can I just add my code right after super? I think it would be too late as the resource would have already been saved. What's the best way to do this?
If I were to write create from scratch, how would I know that I didn't miss anything that Devise does?
Thanks,
According to the Devise documentation, yes, just like Josh's answer, you would change the controller. Although, you don't have to start completely from scratch. Take a look at the documentation.
You can generate the controller so you are able to add customizations:
Example: rails generate devise:controllers [scope]
So, you could run the following for your Users scope:
rails generate devise:controllers users
This gives you the controllers in a folder located here:
app/controllers/users
Then, tell your routes file to use that controller. Update your devise route to look like this:
devise_for :users, controllers: { sessions: "users/sessions" }
And finally, copy over all the views. If you haven't genereated the views yet, you'll need to do so. The controller has changed, so your views will need to as well.
If you want to rewrite the controller from scratch for full control, start with the registration_controller.rb Source Code and make your changes as necessary.
Telling devise to use your custom controller is as simple as changing the route:
devise_for :users, :controllers => { :registrations => "users/custom_controller" }
If you want to fields for user supplied information there's no need to extend controller.
If you want to add those automatically, there's no reason not to do it in model! (unless it depends on session or request)
In 1st case, see https://github.com/plataformatec/devise#configuring-views
You should change DEvise controller ONLY if you intend to change signup flow.
i have an app with nested resources. my routes are:
resources :teams do
resources :blogs
end
in my blogs controller, im using a different layout, by adding
layout "teamlayout"
to the controller.
Both layouts, the application.html.erb and the teamlayout.html.erb have included a login form itself. which i made working by this: https://github.com/plataformatec/devise/wiki/How-To:-Display-a-custom-sign_in-form-anywhere-in-your-app
now my question. when a user logs in, i want him redirected to the page from where he logs in.
You have a couple options:
Include a hidden field value in the login form that describes the source of the login (e.g. hidden_field_tag(:login_source, "team")) and define your own logic for SessionsController#create that uses the hidden field value to determine the location for response_with.
Or, you could keep track of the user's location by using a before_filter in the controllers with login forms by doing something like
def store_location
session['saved_location'] = request.request_uri
end
Then, you can override the after_sign_in_path_for(resource) method in your application controller to use the session saved_location value to determine where to redirect.
The second option seems a little less invasive to the Devise infrastructure to me, but is a little less flexible.