Please let me know if I'm going about this the wrong way. I'm trying to add a couple custom attributes to a User in the create method as well as call my Analytics method if the user is saved.
I defined a new controller:
class RegistrationsController < Devise::RegistrationsController
def create
build_resource(sign_up_params)
resource.public_id = Utilities::generate_code
resource.referral_code = Utilities::generate_code
if resource.save
Analytics.identify(
user_id: resource.id.to_s,
traits: { email: resource.email })
yield resource if block_given?
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
end
The only thing different in this create method is that I'm adding referral_code and public_id before the save and running Analytics after.
Analytics.identify(
user_id: resource.id.to_s,
traits: { email: resource.email })
When I create a user I'm getting
undefined method `is_flashing_format?' for #<RegistrationsController:0x007fdba130d9a8>
I don't understand why this method isn't being inherited. Is this even the proper way to modify devise or to add attributes/add analytics?
I figured it out, I'm using Devise version 3.1.1 (locked for dependencies), it looks like is_flashing_format? was added last month in 3.2.0.
I changed the method in my controller to is_navigational_format? and all is well!
Related
I'm making a simple app that has the traditional User model, but also a Patients model. I want a user to automatically become a patient on sign up.
I've managed to follow instructions here, and can see the file users/registations_controller.rb, but I'm not sure what to add to it.
I have pasted the existing devise create code from here
def create
build_resource(sign_up_params)
resource.save
yield resource if block_given?
if resource.persisted?
if resource.active_for_authentication?
set_flash_message! :notice, :signed_up
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}"
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
set_minimum_password_length
respond_with resource
end
end
and I want to add functionality to do this too:
# #user = User.new(user_params)
#patient = #user.build_patient
#patient.save
But I don't know how to do that? (do I just add the code and replace 'user' with 'resource'?)
You can do it by adding block code like this instead of copy the Devise code
class YourController < Devise::RegistrationsController
def create
super do |user|
#patient = user.build_patient
#patient.save
end
end
end
Because of an api I'm using, I need to take out Devise's registrationsController create action. I have gotten this to work in every way except one. For some reason, the set_flash_message method returns the error:
NoMethodError - undefined method `set_flash_message!' for #<Users::RegistrationsController:0x007f91f8e8b070>:
app/controllers/users/registrations_controller.rb:28:in `create'
Here is the controller code:
class Users::RegistrationsController < Devise::RegistrationsController
def create
build_resource(sign_up_params)
resource.save!
yield resource if block_given?
if resource.persisted?
puts "resource persisted".green
if resource.active_for_authentication?
flash[:success] = "Welcome! You have signed up successfully."
# set_flash_message! :notice, :signed_up
sign_up(resource_name, resource)
respond_with resource, location: after_sign_up_path_for(resource)
else
puts "not sure about this".blue
set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
# flash[:danger] = "signed_up_but_#{resource.inactive_message}"
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
puts "resource did not persist".red
clean_up_passwords resource
set_minimum_password_length
# respond_with resource
puts "NOW WE KNOW".on_red
render 'new' #not sure if this works
end
end
end
I've put in flash messages the normal way for now but it's already causing some problems. How do I get set_flash_message to work?
I ran into the same issue. Turns out this functionality was recently changed in Devise (January 28, 2016).
So you either need to update the version of Devise that you use in your app or use the old way of calling set_flash_message, which was:
set_flash_message :notice, :signed_up if is_flashing_format?
I'm using Devise with my Rails 3.2 app and I want to be able to add track new registrations as conversions in Google Analytics. I'd like to have the new users directed to the same page that they are being redirected to now, if possible (i.e. may be a pass thru view that redirects to the current page users are redirected to after create).
Can someone please help me figure out the best way to do this with Devise?
# users/registrations_controller.rb
# POST /resource
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)
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
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
From the top of my head, I'd use flash.
The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed to the very next action and then cleared out.
On the registrations_controller.rb:
if resource.active_for_authentication?
flash[:user_signup] = true # or something that you find more appropriate
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
Then, on the view that you redirect to after a signup, I'd render the necessary code to trigger a Google Analytics event based on the presence of flash[:user_signup].
You can do it from your controller:
Step 1: in order to keep it organised, you can create a file app/controllers/concerns/trackable.rb with the following content:
module Trackable
extend ActiveSupport::Concern
def track_event(category, action)
push_to_google_analytics('event', ec: category, ea: action)
end
def track_page_view
path = Rack::Utils.escape("/#{controller_path}/#{action_name}")
push_to_google_analytics('pageview', dp: path)
end
private
def push_to_google_analytics(event_type, options)
Net::HTTP.get_response URI 'http://www.google-analytics.com/collect?' + {
v: 1, # Google Analytics Version
tid: AppSettings.google_analytics.tracking_id,
cid: '555', # Client ID (555 = Anonymous)
t: event_type
}.merge(options).to_query if Rails.env.production?
end
end
Step 2: Replace your tracking ID.
Step 3: Finally, track your conversions in your controller:
# app/controllers/confirmations_controller.rb
class ConfirmationsController < Devise::ConfirmationsController
include Trackable
after_action :track_conversion, only: :show
private
def track_conversion
track_event('Conversions', 'from_landing_page')
# or # track_event('Conversions', user.email)
end
end
Extra: you can also use the track_page_view method to track specific actions that don't have views (like API requests).
More info here: https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide.
So, I'd like to add this bit of code to the devise registrations controller.
When I'm calling #user.save. just before that, I need to call, #user.uid = SecureRandom.hex(whatever-value).
However, I don't want to change the way the create action currently functions. I'd just like to add the #user.id = SecureRandom.hex line.
So, how does the original devise create action look?
https://github.com/plataformatec/devise/blob/master/app/controllers/devise/registrations_controller.rb
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?
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
even more docs:
https://github.com/plataformatec/devise/wiki
Use Case:
Admin should be able to create user, and it should not attempt to login.
Public User can crate account and after signup he should be redirected to sign-in page rather signing him in immediately.
Can somebody help me with this ?
Thanks :)
What you need to do is to override Devise's RegistrationsController create method.
There is an excellent explanation for how to do it here.
This is Devise create action:
# POST /resource
def create
build_resource
if resource.save
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
After you override the controller, just remove sign_in(resource_name, resource)
You can also set the method after_sign_up_path_for(resource) to fit your needs