How do I execute a particular function after a user has signed up.
(I wanted to add to one of my associations, I already have it coded in a non-devise rails but now I need it here)
Device has provided helper action 'after_sign_in_path_for' you can override it within your application controller.
def after_sign_in_path_for(resource_or_scope)
.... #write your customize code or call any method
end
For sign up it would look like:
def after_sign_up_path_for(resource_or_scope)
if resource_or_scope.is_a? User # and perhaps other conditions
#... do something, go somewhere
else
super
end
end
Ofc. Assuming that your Devise user model is called User.
You can use the after_create callback in your User model.
The following guide has tons of examples: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
Related
I am using devise gem. I would like to add one more condition check while the user clicks in login button. So far I haven't customized create method in the sessions controller.
I would like to add a condition like if user.valid? There is one field called valid in the database.
What is the best way to do this with devise?
Any guidance or help would be appreciated
Check this documentation, the main idea is to override active_for_authentication?.
class User < ActiveRecord::Base
def active_for_authentication?
super && special_condition_is_valid?
end
end
I'm currently trying to automatically create an user_address (which will be a randomly generated hash, which is for now hardcoded) string upon sign-up with the Ruby on Rails devise Gem. I have added the user_address to the list of allowed parameters I am currently trying to add this logic to the registrations_controller.rb by adding the following method :
def create
super do
current_user.user_address = '1F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX'
end
end
I suppose this is because current_user must not be defined before the actual POST (create user) has been processed but I am not sure about the way to do this.
Any help would be greatly appreciated, thanks in advance
If i understand you correctly (I think I do) you could move away from trying to do this in the create action in the controller and instead use a model callback on the User model.. that way its automatically created when a user registers.
example:
class User < ApplicationRecord
before_create :assign_user_address
validates_uniqueness_of :user_address
def assign_user_address
begin
self.user_address = SecureRandom.hex
other_user = User.find_by(user_address: self.user_address)
end while other_user
end
end
the before_create will generate the user_address and assign it to the user that is registering, while the validates_uniqueness_of ensures that you will never have a duplicate user address all in one fell swoop (although with a random string the chances of duplicating are slim.. but better to be safe than sorry.. I find this method super easy and keeps your controller clean and un cluttered.
Let me know if this wasn't what you were looking for..
I am using Devise for authentication in my application.
How do I forbid certain users from signing in - kind of disable a user?
Do it like this:
Create a column called is_active for the User model.
Then add the code below to the User model:
class User < ActiveRecord::Base
#this method is called by devise to check for "active" state of the model
def active_for_authentication?
#remember to call the super
#then put our own check to determine "active" state using
#our own "is_active" column
super and self.is_active?
end
end
UPDATE
As Matt Huggins notes, the method is now called active_for_authentication? (Documentation)
Add a column to the User model: allowed_to_log_in.
Then add this to /app/models/user.rb:
def active_for_authentication?
super and self.allowed_to_log_in?
end
If you want to inform the user with a custom message you can add this as well:
def inactive_message
"You are not allowed to log in."
end
I think that is quite important because the standard message from Devise says:
"Your account is not activated yet."
That is confusing for users and the real reason is that you have "banned" them from logging in.
You want to do authorization, not authentication. Devise only does authetication, though.
I.e. devise only tells you that a user is who he says he is.
You need something else to forbid him from using the site.
Authorization is a popular topic and there's a whole list of gems that can help you with it:
http://ruby-toolbox.com/categories/rails_authorization.html
Take your pick.
Sounds like you may be interested in cancan
https://github.com/ryanb/cancan
http://railscasts.com/episodes/192-authorization-with-cancan
I am using Devise, and when someone logs in I would like to execute a custom method.
Similarly to how you use before_save to execute a method before the account/model is updated/saved, or before_create to do the same before the object is initially created.
I would like to do the same, but for users logging in.
How do I do that ?
In your application_controller.rb add the following code:
def after_sign_in_path_for(resource)
execute_custom_function()
super
end
You can utilize Devise's Controller Helper.
I am using Devise on Rails and I'm wondering if there is a hook or a filter that I can use to add a bit of code to Devise's user registration process and send a welcome email to the user after an account has been created. Without Devise it would be something like this...
respond_to do |format|
if #user.save
Notifier.welcome_email(#user).deliver # <=======
...
The next most popular answer assumes you're using using Devise's :confirmable module, which I'm not.
I didn't like the other solutions because you have to use model callbacks, which will always send welcome emails even when you create his account in the console or an admin interface. My app involves the ability to mass-import users from a CSV file. I don't want my app sending a surprise email to all 3000 of them one by one, but I do want users who create their own account to get a welcome email.
The solution:
1) Override Devise's Registrations controller:
#registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
super
UserMailer.welcome(resource).deliver unless resource.invalid?
end
end
2) Tell Devise you overrode its Registrations controller:
# routes.rb
devise_for :users, controllers: { registrations: "registrations" }
https://stackoverflow.com/a/6133991/109618 shows a decent (not perfect) answer, but at least better than ones I'm seeing here. It overrides the confirm! method:
class User < ActiveRecord::Base
devise # ...
# ...
def confirm!
welcome_message # define this method as needed
super
end
# ...
end
This is better because it does not use callbacks. Callbacks are not great to the extent that they (1) make models hard to test; (2) put too much logic into models. Overusing them often means you have behavior in a model that belongs elsewhere. For more discussion on this, see: Pros and cons of using callbacks for domain logic in Rails.
The above approach ties into the confirm! method, which is preferable to a callback for this example. Like a callback though, the logic is still in the model. :( So I don't find the approach fully satisfactory.
I solved this by using a callback method. It's not the cleanest of solutions, not as clean as an observer, but I'll take it. I'm lucky Mongoid implemented the ActiveRecord callbacks!
after_create :send_welcome_mail
def send_welcome_mail
Contact.welcome_email(self.email, self.name).deliver
end
I would recommend using a ActiveRecord::Observer. The idea with the observer is that you would create a class with an after_save method that would call the notification. All you need to do is create the observer class and then modify the application configuration to register the observer. The documentation describes the process quite well.
Using the observer pattern means you do not need to change any logic in the controller.
Since a yield has been added to the Devise controller methods a while back, I think this is now probably the best way to do it.
class RegistrationsController < Devise::RegistrationsController
def create
super do |resource|
Notifier.welcome_email(resource).deliver if resource.persisted?
end
end
end