How to create a profile after user registration with Rails3 & Devise - ruby-on-rails-3

I'm doing a simple user with profile application. User registers and
are automatically logged in. Works fine so far. Now, I'd like to
create a profile after a successful registration and redirect the user
to his/her profile.
I have a User model and controller. Devise also created the
registration controller. I installed the gem. I copied over the devise
files and I plan to override the create action.
First, whatever I edit in registrations_controller.rb nothing
changes.
class Devise::RegistrationsController < ApplicationController
prepend_before_filter :require_no_authentication, :only =>
[ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only =>
[:edit, :update, :destroy]
include Devise::Controllers::InternalHelpers
Secondly, how to insert the profile creation step?
def create
build_resource
if resource.save
if resource.active?
set_flash_message :notice, :signed_up
sign_in_and_redirect(resource_name, resource)
else
set_flash_message :notice, :inactive_signed_up, :reason =>
resource.inactive_message.to_s
expire_session_data_after_sign_in!
redirect_to after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords(resource)
render_with_scope :new
end
end
I was thinking to add
current_user.create_profile under is resource.active?
How would you guys tackle that issue?

First, Please format your post and use <code> blocks for the snippets. That way it becomes very readable.
Coming to your problem:
Devise by default sign ins and redirects to application root_path, after registration.
If you wish to redirect to some other path you can specify it in a couple of ways.
One is to specify root_path for your devise reource. So in your case it will be
match '/user/profile/new' => 'profiles#new', :as => 'user_root'
This will redirect you to profile#new every time you login.
To prevent redirecting to profile#new each time you can add a before_filter on profile#new to check if profile exists and redirect to some other page, say dashboards, if profile exists.
Here is the link showing how to change redirect_path for devise:
https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in

Related

Rails devise redirecting to sign in when attempting reset or unlock

Using
ruby 1.9.3p448
Rails 3.2.13
devise (2.2.3)
When a user follows the link from a password reset email or a unlock account email (devise :recoverable, :lockable) they are redirected first to sign in. I have seen in the logs, this is a 302.
I have modified
~/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/actionpack-3.2.13/lib/action_controller/metal/redirecting.rb
so that the redirect method has the following added to the top:
File.open("/home/myname/fooblah.txt", 'a'){|f| f.puts(caller()); f.puts "########"}
So to see where redirect_to is being called. In the caller() chain, no code from the application is calling redirect_to. So I am wondering if there is some bug or quirk which causes this redirect.
Currently a user has to go back to the link in the email and hit it a second time
Update
In .rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/devise-2.2.3/app/controllers/devise/unlocks_controller.rb
# GET /resource/unlock?unlock_token=abcdef
def show
self.resource = resource_class.unlock_access_by_token(params[:unlock_token])
if resource.errors.empty?
set_flash_message :notice, :unlocked if is_navigational_format?
respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
end
end
protected
# The path used after unlocking the resource
def after_unlock_path_for(resource)
new_session_path(resource)
end
... so its default to redirect to root path? But devise.yml says:
unlocked: 'Your account was successfully unlocked. You are now signed in.'
This seems to be an incongruency in the Devise gem...
I guess you have added :authenticate_user! in your application controller and have overridden devise's controllers .
If this is the case you have to add skip_before_filter :authenticate_user! to overridden controllers action

Get current user in invitations controller

I am using devise_invitable gem in my application.
If a user is already signed in the application and he clicks on the Accept Invitation link then he is redirected to devise after_sign_in_path_for.
I want to change that and give the user some flash that he is signed in the application and needs to sign out before continuing.
After clicking on Accept Invitation link my control goes to Users::InvitationsController#edit. But I am not able to get current_user in Invitations Controller.
My routes and action is as:
devise_for :users, controllers: { registrations: "registrations", :invitations => 'users/invitations', sessions: "sessions", confirmations: "confirmations", passwords: "passwords" }
def edit
Rails.logger.debug current_user.inspect
if current_user.present?
Rails.logger.debug "---current user---"
else
render :edit
end
end
Can some one please suggest how I can get the current user in invitations controller.
This is the line in InvitationsController that prevents current_user from being assigned:
prepend_before_filter :require_no_authentication, :only => [:edit, :update, :destroy]
Add this to your controller and current_user will be assigned:
skip_filter :require_no_authentication, :only => :edit

Redirect to root_path after failed Devise user registration

I've read & attempted the solutions posted in numerous SO posts (i.e. here, here, and here) as well as Devise's answer on how to change the path after a failed registration, and Devise's RegistrationsController code, all to no avail.
Instead of doing the custom failure method in the /lib/ folder like most suggest, It seems like the easiest place to fix/override this would be in the RegistrationsController#create method at the bottom where it's:
else
clean_up_passwords resource
respond_with resource
end
It's (I assume) correctly responding with the user (i.e. redirecting them to root_path/users), but here's the tricky part: I create a nested model when my user registers, and that was quite difficult hacking into Devise for that. I'm afraid that if I go messing with the RegistrationsController#create method, that I'll break my perfectly-working nested models.
Someone also mentioned that the Devise solution didn't work for them, but then got it to work after changing a routing problem. I doubt that's the case with me, but here's my routes.rb file just in case:
devise_for :users, :controllers => { :registrations => "registrations" }
resources :users
resources :users do
resources :lockers
end
resources :lockers do
resources :products
end
resources :products
resources :lockups
match '/user/:id', :to => 'users#show', :as => :user
root :to => 'home#index'
I completely appreciate any help anyone can provide me. I'm still pretty new to Rails, but I'm always happy to learn.
EDIT: Thanks to Passionate, I've been trying to figure out how to change the logic in the final else block in the registrations controller. Here's what I've tried (along with my noob logic):
# Obviously cleared all the fields since it made no mention of resource
# redirect_to root_path
# Too many arguments since root_path takes 0
# redirect_to root_path resource
# Just bombed, something about a String somethingorother
# render root_path
# Heh, apparently call 'respond_with' and 'redirect_to' multiple times in one action
# respond_with resource
# redirect_to root_path
First you have to fix routes.rb file . Since you're using custom controller , you also have to customize devise_scope block . Change
get "signup", :to => "devise/registrations#new"
to
get "signup", :to => "registrations#new"
And, if you try to override the method and want to set the root_path after devise rails registration, you can do like
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
build_resource
// The `build_resource` will build the users .
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
## replace your logic here
redirect_to root_path
end
end
end
Please note that the above code works with devise 2.2.4 . Currently, the code which is on master branch on github is changed somewhat due to rails 4 and strong_parameter compatibility .

How to authenticate single action with two devise?

I have implemented two devise(version: 1.4.8) model in my project for example User and Admin.
Is there any option to configure authentication for single action in same controller with two devise?. example for CartsControler:
index, show -> can access either admin or user
create, update, delete -> can access admin only
Currently I have authenticated by calling below method from application_controller.rb
def authenticate_user_or_admin!
unless user_signed_in? or admin_signed_in?
redirect_to root_url , :flash => {:alert => "You need to sign in as admin/user before continuing..".html_safe }
end
end
in carts_controler.rb
class CartsControler < ApplicationController
before_filter :authenticate_user_or_admin!, :only => [:index, :show]
before_filter: :authenticate_admin!, :except => [:index, :show]
Is devise providing any default options to authenticate multiple devise models?
Is this proper ways to solve this problem? or any other better solution?

Devise and Facebook Custom Routing

I am trying to create the user registration views and model on my website but I am having a small issue :
I am using devise and omniauth to get the facebook connect features working and it works,
But I want my facebook users when they sign in the first time to create their password,
That is also working, I redirect them to the filled sign up form and they only have to enter their password. But I want them to go to a second "sign_up form" named /views/registrations/new_facebook.html.erb where they can only enter their password and I will also add some other information,
I created the correct view and tested it but I have no idea how to create the correct routes to bypass Devise default
match '/facebook' => 'registrations#new', :as => 'new_facebook_user_registration'
I believe the issue is with match because that's what's not recognised,
If anyone can help me that would be great thanks,
I added my controller code for omniauth :
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
user = User.from_omniauth(request.env["omniauth.auth"])
if user.persisted?
flash[:success] = "Welcome back"
sign_in_and_redirect user
else
session["devise.user_attributes"] = user.attributes
redirect_to new_facebook_user_registration_url
end
end
alias_method :facebook, :all
end
How can I make the redirect_to new_facebook_user_registration_url actually work ?
devise_scope :user do
match "registrations/new_facebook" => "registrations#new_facebook"
end
That's the solution I copied in the registrations controller the new method and named it new_facebook and now everything is working as expected !
I think the issue is that you're not overriding the devise method that redirects to that path. Also according to the devise docs your routes should be set up with a "devise_for" call.
Here's the wiki page describing how to do what you are asking to do, although you may need a bit of custom logic to deal with cases that aren't facebook signups.
https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-up-(registration)
Some example code from that page:
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
'/an/example/path'
end
end
and the one for routes:
devise_for :users, :controllers => { :registrations => "registrations" }