Devise: creating extra records on user creation - ruby-on-rails

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

Related

Devise Unpermitted First and last name

i am currently trying to sign up/create an account for application using devise on ruby on rails(5.2.2) and ruby version 2.3.7 but i am getting the unpermitted parameter message and tried with Strong parms but it didn't work.
tried this two posts below but didn't work
Rails 4 and Devise: Devise not saving new information (First Name, Last Name, Profile Name)
Rails 4 and Devise: Devise not saving new information (First Name, Last Name, Profile Name)
class Api::V3::ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
before_action :configure_permitted_parameters, if: :devise_controller?
# before_filter :authenticate_user!
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:firstname,:lastname,:username,:password])
# devise_parameter_sanitizer.for(:sign_up) << :provider
# devise_parameter_sanitizer.for(:sign_up) << :uid
end
end
Processing by Devise::RegistrationsController#create as JSON
Parameters: {"user"=>{"email"=>"testuser#gmail.com",
"password"=>"[FILTERED]", "firstname"=>devise", "lastname"=>"test"}}
Unpermitted parameters: :firstname, :lastname
it looks like devise is not accepting parameters and which is resulting in first and last name not stored in local database.
You can override the registration controller and add fields you want.
class RegistrationsController < Devise::RegistrationsController
def create
build_resource(sign_up_params)
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?
respond_with resource, :location => after_sign_up_path_for(resource)
end
else
clean_up_passwords
respond_with resource
end
end
# you will get the full registration controller in devise github repo
private
def sign_up_params
params.require(:user).permit(:email, :first_name, :last_name, :password, :password_confirmation)
end
end
and add the new routes too
devise_for :users, :controllers => { :registrations => 'registrations' }
devise github repo here

Rails devise undefined method `after_sign_in_path_for'

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

how do I create and assign a new object to a user after sign up?

How do you create and assign a new object to the User after a sign up with devise?
I created a Profile model to hold attributes for the User model such as "name" "location" "description" "photo" etc.
I'm using Devise to register users for the User model, which will just hold email and password.
I wanted to separate these attributes out from one User model so user profile attributes can be updated without a password.
I've tried an after_create callback to initialize a new profile object, but it doesn't work.
"undefined local variable or method `current_user' for #"
User.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :profile, dependent: :destroy
after_create :setup_profile
protected
def setup_profile
#profile = current_user.profile.create
end
end
my_devise/registrations_controller.rb
class MyDevise::RegistrationsController < Devise::RegistrationsController
def create
build_resource(registration_params)
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?
respond_with resource, :location => after_sign_up_path_for(resource)
end
else
#clean_up_passwords
respond_with resource
end
end
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 their password changed
sign_in #user, :bypass => true
redirect_to after_update_path_for(#user)
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? ||
params[:user][:password_confirmation].present?
end
# https://github.com/plataformatec/devise/wiki/How-To%3a-Allow-users-to-edit-their-account-without-providing-a-password
def needs_pass?(user, params)
params[:password].present?
end
def registration_params
params.require(:user).permit(:email, :username, :password, :password_confirmation)
end
def user_params
params.require(:user).permit(:name, :username, :location, :description, :website)
end
protected
def after_update_path_for(resource)
edit_user_registration_path(resource)
end
def after_sign_up_path_for(resource)
current_user
end
end
current user is not available in model. And when you use callback you are actually referring to that object that you work with (the user that signs up).
after_create :setup_profile
def setup_profile
profile = self.create_profile # or Profile.create(user_id: self.id)
end

Rails call controller action on successful object save

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

Comma separated value not being stored

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

Resources