Rails devise before_destroy user - ruby-on-rails

I wan't to notify the admin when a user deletes his account. My idea is to use the before_destroy validation to send an email from within the model.
This is probably better done in the controller but I don't want to subclass the devise controller because I think I could break something.
The problem is that the model can't access the current_user, which was my first thought about how to "get" the corresponding user account. But the model has to somehow know which user account is meant to be destroyed, right?, so there has to be some kind of variable being passed.
I've looked into the devise controller at github and it seems like everything is done using "resources".
https://github.com/plataformatec/devise/blob/master/app/controllers/devise/registrations_controller.rb
I can't figure out the last part, how could I access the id / or user object?

Simple add a hook in your model and send the mail..
class User < ActiveRecord::Base
before_destroy :notify_admin
private
def notify_admin
YourMailer.user_destroyed(self).deliver
end
end
The "self" will be your current_user object..

Something like that could work:
class Users::RegistrationsController < Devise::RegistrationsController
def destroy
# You have access to current_user here
super
end
end

Related

Add an empty nested object to newly created user in Devise

I have a User model in my Rails 5 app using Devise.
I also have a relationship: user belongs_to account.
Now, when I create a new user I want to automatically create a new empty account for it.
I already have my registrations controller and a method:
def create
super
end
I would like to do something like this:
def create
super
user.account.create()
end
Are you looking for something like that ?
In your model User.rb
after_create do
self.account = Account.create() if self.account.nil?
end
In devise controllers, user object is called as resource by default. So something like this will work:
def create
super
if resource.persisted? # user has been created with no errors
resource.account.create # assuming it will pass validations without arguments
end
end
Another way, as #julien-js mentioned, is to create account in after-create hook, but instead of after_create you can use after_commit(read more about the difference):
after_commit :create_account, on: :create
def create_account
self.account.create unless self.account.present?
end

Best name for a Rails controller?

I'm writing a simple Rails app and I'm wondering what to name a controller that creates accounts.
Some background: Users create a schedule and it's publicly visible. There are users and events. An event can have multiple event_sessions. That's pretty much it.
During registration a user is created, an event is created, and sessions are created. So where do I put this, the UsersController? And, if account creation includes all this other stuff, do I put it in a new controller? If so, what do I call the controller — ExternalSiteController? AccountController?
I would start with something like the following, and tweak as necessary:
class UsersController < ActionController::Base
def create
# ...
User.create(user_params)
# ...
end
end
class User < ActiveRecord::Base
after_create :setup_initial_event
has_many :events
DEFAULT_EVENT_PARAMS = {
# ...
}
def setup_initial_event
events.create(DEFAULT_EVENT_PARAMS)
end
end
class Event < ActiveRecord::Base
after_create :setup_initial_sessions
belongs_to :user
has_many :sessions
def setup_initial_sessions
# You get the idea
end
end
If you don't have an account model (in which case AccountsController would be perfect), I'd put the code in the UsersController. User is probably the most complex and important model of the three (the registration of a user is what's kicking everything off, after all). Of course, you can create any object in any controller (i.e. you can call User.create() in the EventsController).

Rails/Devise: execute action after automatic login

EDIT: I use Devise 3.4.1, and after_remembered isn't available. Either apply this small patch or use a newer version released after 2014/11/09.
Alright, so I am rather new to the Rails environment, and I feel I am missing something.
I wish to execute a particular action after login, be it after login from a form or automatic login.
I found out that after_sign_in_path_for is executed after a "regular" login. I already use it in my Application controller.
class ApplicationController < ActionController::Base
[…]
def after_sign_in_path_for(resource)
myAction
end
However, it seems that this method isn't called when a user is logged in through the Devise Remember option.
I found out that after_remembered is executed after a user is automatically logged in, however I don't understand how to use it. I don't want to modify the Devise gem just to add my action to the method, and the following doesn't seem to work:
class ApplicationController < ActionController::Base
[…]
def after_remembered()
myAction
end
I am at a loss here. Either I don't understand how to use after_remembered, or I look at it the wrong way and there is another solution for that (should it cover either both cases or only the case with "remember me" automatic login, is fine for me). Does anyone have any idea to make it work?
PS: I am working on an app I haven't developed myself. If you feel you need more code in order to answer, tell me and I will edit my post.
It's part of the Rememberable module so it belongs in your model... assuming your resource is User the way you would use it is...
class User < ActiveRecord::Base
devise :rememberable
def after_remembered
# (your code here)
end
end
I'm not sure if Devise offers a controller-specific method but if not you could throw one togeter... create an attribute in your User model called, say, signed_in_via_remembered
class User < ActiveRecord::Base
devise :rememberable
def after_remembered
update_attribute(:signed_in_via_remember, true)
end
end
then in your application_controller.rb
class ApplicationController < ActionController::Base
before_action :handle_sign_in_via_rememberable
def handle_sign_in_via_rememberable
if current_user and current_user.signed_in_via_remember?
current_user.update_attribute(:signed_in_via_remember, false)
after_sign_in_path_for(User)
end
end
def after_sign_in_path_for(resource)
myAction
end
end
Someone may have a neater solution.

Devise: Allow only admin to create users

I have a Rails 4 app. It is working with devise 3.2.3. devise is properly integrated. At this point, users can register with email and password, sign in and perform CRUD operations.
Now here is what I would like to do: Instead of having any user to sign up by themselves, I want to create an admin. The admin would retain the responsibility of creating users. I don't want users to sign up by themselves. Basically the admin will create the user, issue them their log-in credentials, and email it to them.
I read this post and similar ones in SO and in devise wikis to no avail.
I have added a boolean field to users table to identify admin users.
class AddAdminToUser < ActiveRecord::Migration
def change
add_column :users, :admin, :boolean, :default => false
end
end
I have read about managing users using cancan but I don't know how to use it to achieve my objective
The solution i'm looking for would probably require a combination of devise and cancan.
I would appreciate any guidance on this matter.
Make sure that the boolean :admin is not in your params.permit() area for strong parameters.
Use the pundit gem, it is maintained and pretty much plain old ruby objects.
Then in your UserPolicy you would do something like this
class UserPolicy < ApplicationPolicy
def create?
user.admin?
end
end
And your model would look something like this
class User < ActiveRecord::Base
def admin?
admin
end
end
Last in your controller you make sure that the user is authorized to do the action
class UserController < ApplicationController
def create
#user = User.new(user_params)
authorize #user
end
end
You would probably also want to restrict the buttons that are shown that would give access to the admin user creation section. Those can be done with pundit as well.

What's the best way to make a new model when overriding the Devise User Controller?

I'm trying to make it so that when a new User is created (through Devise), a new Household(essentially a group) model will be created if no previous Household model with that name exists.
pseudocode:
if Household.find(params[:household_name))
# allow current_user to join household
else
# create new Household model with User's household_name parameter
end
I've overwritten the base user controller from Devise::RegistrationsController with controllers/registerhousehold_controller.rb:
class RegisterhouseholdController < Devise::RegistrationsController
But I'm not sure how to implement the actual creation here. Any suggestions?
No changes in controller required as far as I see.
User.rb
after_create :create_or_join_to_household
def create_or_join_to_household
household = Household.find(params[:household_name])
if household.present?
self.join_to_household
else
Household.create(name: params[:household_name])
#or self.households.create(name: params[:household_name])
#if you have a household - user relation somehow
end
p.s.
join_to_household would be another method in your user model that will create a household_users relation.
Simple - use the before_create callback in the user model to build the object, then you'll be able to use it when you save:
#app/models/user.rb
Class User < ActiveRecord::Base
before_create :set_household, if: Proc.new {|user| user.household_id.present? }
private
def set_household
if house = Household.find(self.household_id)
#if it is set
else
#create a new houshold
end
end
end
I had to call custom method after successful sign up, on my previous task.
U also need something similar.
I'm not sure about overriding.
Try this in App. controller
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
if Household.find(params[:household_name))
# allow current_user to join household
else
#create new Household model with User's household_name parameter
end
root_path
end
end
Check this

Resources