I had override Devise's RegistrationsController to send a welcome email when a user signup. Trying to use Roadie for some inline style modification for the email before sending out but an uninitialized constant Users::RegistrationsController::Roadie was shown on the line calling Roadie:
app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def create
# Call the original Devise Create
super
if resource.save
## New version with inline css styling
## Things done in the hacky way
email = UserNotifier.send_signup_email(resource)
doc = Roadie::Document.new email.body.to_s
doc.add_css(Rails.application.assets["email"].to_s)
email.body = doc.transform
email.deliver
..
So, when I call Roadie above, instead of the Roadie Class in the gem it try to call Users::RegistrationsController::Roadie. Gem was installed when checking with bundle show. Have been trying to look into devise code to see if there're kind of scooping (I am not sure there's such thing in Controller indeed) but no luck as well. I guess it should be super simple so hope someone could help!
And of course.. The above code works in console. :)
Thank you!
Related
I hooked up devise_invitable gem
And everything is working correctly in my dev environment. I can view the mailer html in the terminal, I can copy the URL with the token it sends. And when I put that in browser and go to that path it works perfectly.
I would however like to create a preview for this so I can preview the mailer as I get that part how I want it.
Here's what I've tried so far.
In test/mailers/previews
and my code is something like this:
class InviteAdminPreview < ActionMailer::Preview
def invite
InviteAdminMailer.invite(Admin.last)
end
end
but this isn't really working because I don't know what the actual invite mailer is called. Because in app/mailers where I would have expected devise_invitable to place this mailer, there is nothing there.
So should I create my own mailer here called InviteAdminMailer? Or is there some other way to do it?
Also will i have to create this .invite method myself in this mailer so this preview will work?
First of all, to create a customized mail for devise_invitable usage, you can reference the article "Customizing for different Invite use cases (emails etc.)" https://github.com/scambra/devise_invitable/wiki/Customizing-for-different-Invite-use-cases-(emails-etc.) from devise_invitable wiki.
According to devise_invitable source code ( https://github.com/scambra/devise_invitable/blob/cf77519ca9d02c112d99fd176a8852272c1b8d99/lib/devise_invitable/models.rb#L210 ), it uses the mailer provided by devise, so there is no devise_inviatble mailer. If you want to preview devise mails, you can do something as below:
From: https://gist.github.com/ThawanFidelis/ac4a215b841619eae7d8
# config/enviroments/development.rb
config.action_mailer.preview_path = "#{Rails.root}/app/mailer_previews"
# app/mailer_previews/devise_mailer_preview.rb
class Devise::MailerPreview < ActionMailer::Preview
def confirmation_instructions
Devise::Mailer.confirmation_instructions(User.first, {})
end
def unlock_instructions
Devise::Mailer.unlock_instructions(User.first, "faketoken")
end
def reset_password_instructions
Devise::Mailer.reset_password_instructions(User.first, "faketoken")
end
end
This worked for me
def invitation_instructions
Devise::Mailer.invitation_instructions(User.all.sample, 'faketoken')
end
I've had the following setup to send the user a welcome email after a successful registration.
class RegistrationsController < Devise::RegistrationsController
def create
super
unless #user.invalid?
UserMailer.delay.welcome(#user)
end
end
end
I'm on Rails 4.1.4 and I recently updated all gems, which updated Devise to 3.2.4. After the update, the above started throwing the following error:
wrong number of arguments (1 for 2)
app/controllers/registrations_controller.rb:4:in `create'
Seems like calling super is what is breaking things.
Please advice.
This wasn't Devise fault, but rather the following Turbolinks change broke redirect_to https://github.com/rails/turbolinks/commit/153f1b0f04c718442cfd73365a2778dfe1a1c5c7
Rolling back to Turbolinks 2.2.2 or 3f2b6e752acde1d9a59a75c48401dfb152afe154 solved the problem.
I'm trying to apply this post ( Devise update user without password ) for users don't need to insert password to update informations.
But, I'm very confused where is this controller. Devise don't create any controller in my app/controller folder. I search in all the folders but I cant find.
Where I that controller?
I see posts talking about create a new controller, but I just want to modify little things.
You don't edit (or shouldn't) the Devise controllers. Instead you create your own controller and inherent from the Devise controller.
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def update
# add custom update logic here
end
end
Notice how RegistrationsController inherets from Devise::RegistrationsController. Now you can overide the registration methods (or modify them and call super). Even the page you are referencing about overriding the devise default behavior relies on class inheritance.
JTG offers good advice, you shouldn't edit the gem directly. As a more direct answer to the question:
To print the folder of your gem:
$ bundle show devise
To open the gem in a text editor ( while being sure not to change anything )
$ bundle open devise
I'm using devise and acts_as_tenant gem and it seems the devise controllers don't inherit from ApplicationController (???) so don't have access to set_current_tenant_by_subdomain
When the password reset link is clicked I get no Tenant scoping by subdomain.
So how do you handle this? Is there an easy way to open up the DeviseControllers to ensure
set_current_tenant_by_subdomain is called?
Thanks so much
There are a few steps to solve this.
Customize the Devise views to include the tenant details. You can do it by using rails generate devise:views and editing the generated views.
Patch DeviseController so that it includes set_current_tenant_by_subdomain. DeviseController is inherited by the device controllers (confirmations, registrations, forgot password, etc.)
The patching would look something like this:
class DeviseController < Devise.parent_controller.constantize
set_current_tenant_by_subdomain(:account, :subdomain)
end
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