I've found that one useful way of doing this without changing devise internals is to dynamically generate the link inside the confirmation_email template.
If you haven't already done so, you should use the devise views generator to create local versions of all devise views in your app.
This is the url generator in the confirmation email template:
confirmation_url(@resource, :confirmation_token => @resource.confirmation_token)
You could replace the parameters with a param generator that holds custom logic to dynamically generate the appropriate link based on the scenario, maybe something like:
confirmation_url(@resource, generate_confirmation_params_for(@resource))
and perhaps in your application_helper, you'd have that method:
def generate_confirmation_params_for(resource)
confirmation_params = {}
confirmation_params[:confirmation_token] = resource.confirmation_token
confirmation_params[:param_2] = 'whatever' if resource.passes_this_test?
(etc…)
confirmation_params
end
One small caveat is that you'll have to create an initializer for helper methods to be available to ActionMailer, which is pretty trivial and I find it to be a good, useful idea. You'd do that by something like this in app/config/initializers/action_mailer_helpers.rb (new file, call it whatever you want):
class ActionMailer::Base
add_template_helper(ApplicationHeper)
end
Lastly, this does require you to override the confirmation acceptance, so whether that be by overriding the method that the confirmation_url points to, or by changing the url altogether to point to a custom action. Because something like a confirmation acceptance doesn't do that much (I believe it just finds the confirmation token in the users table and nils it out and redirects you to the after_sign_in_path_for(resource) url), you can go either way with it. For my needs, I just wrote a custom route. I also didn't do it with confirmations, I did with it Devise::Invitation, but it's virtually the same set of steps.
This is just a less hack-ish way of doing what you want; rather than fiddling with the devise internals. Hope this helps you or someone out.
-Hassan