35

Is there a way to create a after_confirmation :do_something ?

The goal is to send an e-mail after the user confirms using Devise :confirmable.

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
donald
  • 23,587
  • 42
  • 142
  • 223

8 Answers8

90

I'm using Devise 3.1.2, it has a placeholder method after_confirmation which is called after the confirmation finished successfully. We just need to override this method in User model.

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :confirmable

  # Override Devise::Confirmable#after_confirmation
  def after_confirmation
    # Do something...
  end
end

See: Devise 3.5.9 Source Code: https://github.com/plataformatec/devise/blob/d293e00ef5f431129108c1cbebe942b32e6ba616/lib/devise/models/confirmable.rb

Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164
Blue Smith
  • 8,580
  • 2
  • 28
  • 33
  • for some reason I'm getting `undefined method `after_confirmation' for User` ... could this be a devise configuration issue? – s2t2 Sep 29 '14 at 21:13
  • This doesn't work when you want to use the dirty attributes of the model, like `confirmed_at_changed?` or `confirmed_at_was`. Using a traditional `before_save` is the best solution for that, as suggested in the chosen answer's comment [here](http://stackoverflow.com/questions/4558463/rails-devise-after-confirmation#comment12853945_4558910). – Anjan Jan 08 '15 at 19:24
  • method link is [here](http://www.rubydoc.info/github/plataformatec/devise/Devise/Models/Confirmable:after_confirmation) – Arup Rakshit Jun 29 '15 at 08:44
  • 1
    @Anjan you can use `previous_changes` as described [here](http://stackoverflow.com/a/20657833/2643846). – aandis Nov 11 '16 at 02:30
  • 1
    Is it possible to make the difference between confirmation and reconfirmation after a user changed his email ? – Cyril Duchon-Doris Jun 06 '18 at 14:12
  • This still works in Devise 4.7.3 and Rails 6.1. – bjnord Apr 11 '21 at 00:05
  • The OP says it's a "placeholder" method (correctly) and "override" (slightly confusingly). By default, this is an empty method (as of Devise 4.8.0). So, you can write whatever in the method and it would not *override* the default setting. – Masa Sakano Jun 25 '21 at 18:59
24

For new versions of devise 3.x :

See a different answer http://stackoverflow.com/a/20630036/2832282

For old versions of devise 2.x :

(Original answer)

but you should be able to put a before_save callback on the user (extra credit for using an observer) and check if confirmed_at was just set by devise. You can do something like:

  send_the_email if self.confirmed_at_changed?

http://api.rubyonrails.org/classes/ActiveModel/Dirty.html for more details on checking the change on the field.

Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164
njorden
  • 2,606
  • 20
  • 23
  • 23
    If you want it to send only the first time they confirm, the following should work well. `after_save :send_welcome_email, :if => proc { |l| l.confirmed_at_changed? && l.confirmed_at_was.nil? }` – RyanJM Apr 06 '12 at 17:08
  • 2
    For future readers, [this answer](http://stackoverflow.com/a/20630036/2832282) highlighted that there is now an official callback `after_confirmation` that can be overriden on your user model – Cyril Duchon-Doris Mar 24 '16 at 00:37
11

You can override the confirm! method:

def confirm!
  super
  do_something
end

Discussion about the topic is at https://github.com/plataformatec/devise/issues/812. They say that there are no callbacks like after_confirmation :do_something because that approach would require a lot of different callbacks.

Bernát
  • 1,362
  • 14
  • 19
6

Rails 4:

combining multiple answers above

  def first_confirmation?
    previous_changes[:confirmed_at] && previous_changes[:confirmed_at].first.nil?
  end

  def confirm!
    super
    if first_confirmation?
      # do first confirmation stuff
    end
  end
noli
  • 15,927
  • 8
  • 46
  • 62
3

according to the Devise 3.5.9 source code, you can simply define a method on the Devise Resource model, e.g.:

  class User < ActiveRecord::Base
  ...
    def after_confirmation
       do_something
    end
  end

See: Devise 3.5.9 Source Code: https://github.com/plataformatec/devise/blob/d293e00ef5f431129108c1cbebe942b32e6ba616/lib/devise/models/confirmable.rb

Tilo
  • 33,354
  • 5
  • 79
  • 106
1

You can override the confirm! method on your model

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :confirmable

  def confirm!
    super
    do_something
  end
end

There is a discussion about the topic is https://github.com/plataformatec/devise/issues/812. I tried this way, and it worked great.

goma
  • 955
  • 9
  • 15
1

I don't see that callback too, maybe you can try to override the confirmation method and call your callback there.

def send_confirmation_instructions(attributes={})
  super(attributes)
  your_method_here
end
dombesz
  • 7,890
  • 5
  • 38
  • 47
0

We're combining answers from @Bernát and @RyanJM:

def confirm!
  super
  if confirmed_at_changed? and confirmed_at_was.nil?
    do_stuff
  end
end

This seems a bit more performance aware and safe than the two answers separately.

toobulkeh
  • 1,618
  • 1
  • 14
  • 22