I have a user sign up form generated by devise. When the form is submitted and the user object is saved to the database I would like to create and save another object, generated in a separate controller (leads_controller.rb) and pass the user object that was just saved. The sign up form is collecting email, password and password confirmation.
Once the user is saved, I need to pass that user object to the leads_controller to call the new and create actions.
leads_controller.rb
class LeadsController < ApplicationController
include Databasedotcom::Rails::Controller
def new
#lead = Lead.new
end
def create
lead = Lead.new(params[:lead])
lead.Email = #user.email
end
end
routes.rb
# User route
devise_for :users
devise_for :lenders, skip: :sessions, :controllers => {:registrations => "lenders/registrations"}
devise_for :businesses, skip: :sessions
root :to => 'business_account#dashboard', :constraints => lambda { |request| request.env['warden'].user.class.name == 'Business' }, :as => "business_root"
root :to => 'lender_account#dashboard', :constraints => lambda { |request| request.env['warden'].user.class.name == 'Lender' }, :as => "lender_root"
# Leads route
resources :leads
registrations_controller.rb
class Lenders::RegistrationsController < Devise::RegistrationsController
before_filter :update_sanitized_params
def new
super
end
def create
super
end
def update
super
end
private
def update_sanitized_params
devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:email, :password, :password_confirmation, :type)}
end
end
Is there an action I can put in my registrations_controller.rb to pass the user object to leads_controller.rb?
Copy the content from
https://github.com/plataformatec/devise/blob/master/app/controllers/devise/registrations_controller.rb
and paste into registrations_controller.rb
Change routes.rb
# User route
devise_for :users, :controllers => { :registrations => "registrations" }
devise_for :businesses, skip: :sessions
root :to => 'business_account#dashboard', :constraints => lambda { |request| request.env['warden'].user.class.name == 'Business' }, :as => "business_root"
root :to => 'lender_account#dashboard', :constraints => lambda { |request| request.env['warden'].user.class.name == 'Lender' }, :as => "lender_root"
# Leads route
resources :leads
In registration_controller.rb change the create action as
NOTE:- see also the change in create action
def create
build_resource(sign_up_params)
resource_saved = resource.save
yield resource if block_given?
if resource_saved
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_flashing_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_flashing_format?
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
respond_with resource
end
end
In registration_controller.rb
def after_sign_up_path_for(resource)
redirect_to new_lead_path
#after_sign_in_path_for(resource)
end
Devise provide a helper method current_user by which you can know user object in leads_controller.rb and also in views
class LeadsController < ApplicationController
include Databasedotcom::Rails::Controller
def new
#lead = Lead.new
end
def create
lead = Lead.new(params[:lead])
lead.email = current_user.email
end
end
Related
I have controller
class SessionsController < Devise::SessionsController
respond_to :js
layout false
def create
self.resource = warden.authenticate(auth_options)
if resource && resource.active_for_authentication?
sign_in(resource_name, resource)
end
end
end
and my template for it
create.js.erb
<% if user_signed_in?%>
<%= after_sign_in_path_for(resource) %>
<% else %>
Erorrs here...
})
<% end %>
I want redirect to specific page after sign in but have got
NoMethodError - undefined method `after_sign_in_path_for' for #<#<Class
what should i do to fix it?
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks",:confirmations => "confirmations",:passwords => "passwords", :sessions => "sessions" }
end
I have a similar implementation can you try this
class Devise::SessionsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
def create
self.resource = warden.authenticate(auth_options)
if resource && resource.active_for_authentication?
sign_in(resource_name, resource)
end
respond_with resource, :location => after_sign_in_path_for(resource)
end
end
In ApplicationController
private
def after_sign_in_path_for(resource)
stored_location_for(resource) || request.referer || root_path
end
What i want is if somebody enter wrong information when signing up or signing in to be redirected to a different page other than default let's say mycontroller#index
In my application i'm already overidding Devise::SessionsController and Devise::RegistrationsController.I followed the steps from this link Devise redirect after login fail
But still i get redirected to signup page and signin page. I am using Rails 3.2 and Devise 3.4.1
Here is my code....What am i doing wrong or missing?Thank you in advance.
Session controller
class SessionsController < Devise::SessionsController
def create
resource = warden.authenticate!(:scope => resource_name, :recall => "# {controller_path}#failure")
sign_in_and_redirect(resource_name, resource)
end
def sign_in_and_redirect(resource_or_scope, resource=nil)
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource ||= resource_or_scope
sign_in(scope, resource) unless warden.user(scope) == resource
return render :json => {:success => true}
end
def failure
return render :json => {:success => false, :errors => ["Login failed."]}
end
end
Registrations controller
class RegistrationsController < Devise::RegistrationsController
def create
build_resource
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
return render :json => {:success => true}
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
return render :json => {:success => true}
end
else
clean_up_passwords resource
return render :json => {:success => false}
redirect_to {:controller=>"deal",:action=>"confirm_and_pay"}
end
end
def sign_up(resource_name, resource)
sign_in(resource_name, resource)
end
end
Routes
devise_for :users, :skip => [:registrations, :sessions]
devise_scope :user do
get 'signup' => 'devise/registrations#new', :as => :new_user_registration
post 'signup' => 'devise/registrations#create', :as => :user_registration
get 'users/cancel' => 'devise/registrations#cancel', :as => :cancel_user_registration
get 'users/edit' => 'devise/registrations#edit', :as => :edit_user_registration
put 'users' => 'devise/registrations#update'
delete 'users/cancel' => 'devise/registrations#destroy' ,:as=>:destroy_user_session
get 'signin' => 'devise/sessions#new', :as => :new_user_session
post 'signin' => 'devise/sessions#create', :as => :user_session
get 'signout' => 'devise/sessions#destroy', :as => :destroy_user_session
end
Application controller
class ApplicationController < ActionController::Base
protect_from_forgery
def after_sign_up_path_for(resource)
show_deals_path(resource)
end
def after_sign_in_path_for(resource)
sign_in_url = url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => 'http')
if request.referer == sign_in_url
super
else
stored_location_for(resource) || request.referer || root_path
end
end
end
lib/custom_failure.rb
class CustomFailure < Devise::FailureApp
def redirect_url
redirect_to {:controller=>"mycontroller",:action=>"index"}
end
def respond
if http_auth?
http_auth
else
redirect
end
end
end
application.rb
config.autoload_paths += %W(#{config.root}/lib)
If you want to follow Devise redirect after login fail link, you should add this into config/initializers/devise.rb
config.warden do |manager|
manager.failure_app = CustomFailure
end
User signed up
User received confirmation email
User click on user_confirmation_url(#resource, :confirmation_token => #token)
User goes to /users/confirmation.39?confirmation_token=V-UwSF5qzCt8mBVAFuwK
It get this error
If i manually change the url to: users/confirmation/39?confirmation_token=V-UwSF5qzCt8mBVAFuwK
I get this error: The action 'confirmation' could not be found for UsersController
Routes.rb
App::Application.routes.draw do
get "pages/quickstart"
get "pages/configuration"
get "pages/invoices"
get "/reports" => "reports#index"
get "/reports/historical_data" => "reports#historical_data", as: :historical_data
#get "statements/document/month/:date" => "statements#month", :document => true, as: :monthly_statements_document
#get "statements/month/:date/" => "statements#month", as: :monthly_statements
resources :reminders
resources :reminder_users
resources :forecasts
resources :statements
resources :monthly_statements
resources :fuel_cards
resources :accounts_payables
resources :accounts_receivables
resources :customers
resources :invoices
resources :suppliers
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
devise_for :users, :controllers => { :registrations => "registrations"}
# You can have the root of your site routed with "root"
root 'pages#quickstart', as: :home
get "/home" => "home#welcome"
get "/registrations", to: redirect('/users/edit')
get "/user", to: redirect('/users/edit')
get "/user/change_password", as: :change_password
match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
end
(I use this to allow user to edit their profile)
user_confirmation POST /users/confirmation(.:format) devise/confirmations#create
new_user_confirmation GET /users/confirmation/new(.:format) devise/confirmations#new
GET /users/confirmation(.:format) devise/confirmations#show
Model
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
UserController
class UsersController < ApplicationController
before_filter :authenticate_user!
def edit_password
#user = current_user
end
def update_password
#user = User.find(current_user.id)
if #user.update(user_params)
# Sign in the user by passing validation in case his password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
private
def user_params
# NOTE: Using `strong_parameters` gem
params.required(:user).permit(:password, :password_confirmation)
end
end
RegistrationController
class RegistrationsController < Devise::RegistrationsController
def update
#user = User.find(current_user.id)
successfully_updated = if needs_password?(#user, params)
#user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
else
# remove the virtual current_password attribute
# update_without_password doesn't know how to ignore it
params[:user].delete(:current_password)
#user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
end
if successfully_updated
set_flash_message :notice, :updated
# Sign in the user bypassing validation in case his password changed
sign_in #user, :bypass => true
#redirect_to after_update_path_for(#user)
redirect_to edit_user_registration_path
else
render "edit"
end
end
private
# check if we need password to update user data
# ie if password or email was changed
# extend this as needed
def needs_password?(user, params)
user.email != params[:user][:email] ||
params[:user][:password].present?
end
end
devise (3.4.1)
The issue here is with the view generators.
Do you see, in your path, you are getting users/confirmation.39 for your confirmation route...that 39 is being interpreted as a format by your controller. Its not expecting a user id (#resource) if you have a look at rake routes
the answer here is to remove #resource from your url_helper in the email/view, and if needed, pass ID in as a parameter with the token
user_confirmation_url(confirmation_token: #token, id: #resource)
I have a model called org and department. Whenever a organization sign up, it must create a list of departments it has by entering the name of departments as comma separated value. The department list can also be edited later. These are my models:
0rg
class Org < ActiveRecord::Base
has_many :departments, dependent: :destroy
attr_accessible :name, :website, :department_list
validates :name, presence: true
validates :website, presence: true
def department_list
departments.collect { |d| d.department_name }.join(', ')
end
def department_list=(text)
if id && text
departments.destroy_all
text.split(',').each do |d|
departments.create(department_name: d.strip.capitalize)
end
end
end
end
Department
class Department < ActiveRecord::Base
attr_accessible :department_name, :org_id
belongs_to :org
end
My view
<%= f.text_area :department_list, :cols => "10", :rows => "10" %>
Problem:
When the organization sign up by entering the department name as comma separated value, it is not stored in the database. But when the organization updates the field later by edit action, only then department name is stored and it can be further edited at any time. I want the department name to be stored when organization sign up.
Please Help.
EDIT:
My Registration Controller:
class Webs::RegistrationsController < Devise::RegistrationsController
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
# GET /resource/sign_up
def new
build_resource({})
respond_with self.resource
end
# POST /resource
def create
build_resource(sign_up_params)
# customized code begin
# create a new child instance depending on the given user type
child_class = params[:web][:user_type].camelize.constantize
resource.role = child_class.new(params[child_class.to_s.underscore.to_sym])
# first check if child instance is valid
# cause if so and the parent instance is valid as well
# it's all being saved at once
valid = resource.valid?
valid = resource.role.valid? && valid
# customized code end
if valid && 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
render :new
end
end
# GET /resource/edit
def edit
render :edit
end
# PUT /resource
# We need to use a copy of the resource because we don't want to change
# the current user in place.
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
if resource.update_with_password(account_update_params)
resource.role.update_attributes(params[:org])
resource.role.update_attributes(params[:user])
if is_navigational_format?
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
:update_needs_confirmation : :updated
set_flash_message :notice, flash_key
end
sign_in resource_name, resource, :bypass => true
respond_with resource, :location => after_update_path_for(resource)
else
clean_up_passwords resource
render :edit
end
end
end
How do I create extra records when a user creates an account with devise?
Using a HABTM association between a User and Team model, I'm trying create a team that the user is associated with on there account creation.
Below is the code that I have attempted to use.
class RegistrationsController < Devise::RegistrationsController
def create
super
current_user.teams.create(:name => 'User Name')
end
end
I have also tried this
class RegistrationsController < Devise::RegistrationsController
def create
build_resource
if resource.save
resource.teams.create(:name => 'User Name')
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_in(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
respond_with resource
end
end
end
I solved this by changing routes.rb to point to the customised controller.
routes.rb
devise_for :users,
:controllers => { :registrations => "registrations" }
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
super
resource.teams.create(:name => 'User Name')
end
end
You can use a before_save in your model like this :
class User < ActiveRecord::Base
# ... your code ...
after_create :set_user_on_team
# ... your code ...
private
def set_user_on_team
teams.create(:name => username)
end
end
See the doc here : http://guides.rubyonrails.org/active_record_validations_callbacks.html#available-callbacks