I have a before action in a user mailer file, which is supposed to stop mailers sending if a column on user
is set to true or false. However current user is currently unavailable. I understand why, but was wondering if there was a way to do this.
I want to avoid adding the check_if_users_can_receive_mailers
at the top of each mailer method.
before_action :check_if_users_can_receive_mailers
#methods that send mailers
private
def check_if_users_can_receive_mailers
current_user.send_mailers?
end
CodePudding user response:
You have to make the current user available as a attribute or class variable. The most straight forward method is something like this:
class MailerBase < ActionMailer::Base
before_action :check_if_users_can_receive_mailers
attr_accessor :user
def initialize(user)
@user = user
end
private
def check_if_users_can_receive_mailers
user.send_mailers?
end
end
class SomeMailerClass < MailerBase
end
CodePudding user response:
In Rails only your controller and views are request aware. Mailers and models and other classes in your application are not and they cannot get the current user since they can't access the session nor the method current_user
which is a helper method mixed into your controller (and the view context).
If your mailers need to know about the current user the most logical approach is to pass that information into the mailer:
class UserMailer < ApplicationMailer
def intialize(user)
@user = user
end
end
However a mailer should only have one job - to send emails and it shouldn't be questioning if it should do the job or not. Determining if you should send an email to the user should be done elsewhere. You can place this logic in the controller or even better in a service object:
# app/notifiers/user_notifier.rb
class UserNotifier
def initialize(user, event:)
@user = user
@event = event
end
def notify
if @user.wants_email?
spam_user!
end
send_in_app_notification
end
def self.notify(user, event:)
new(user, event:)
end
private
def spam_user!
# ...
end
def send_in_app_notification
# ...
end
end
class ThingsController
def create
@thing = Thing.new
if @thing.save
UserNotifier.notify(current_user, event: :thing_created)
redirect_to @thing
else
render :new
end
end
end