I'm following this tutorial: https://github.com/sendgrid/sendgrid-ruby/. Very straightforward. However, I want to avoid having a big chunk of code in my controller to send an email. It currently looks like this:
from = Email.new(email: '[email protected]')
to = Email.new(email: '[email protected]')
subject = 'Sending with SendGrid is Fun'
content = Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: 'key')
response = sg.client.mail._('send').post(request_body: mail.to_json)
Ideally, I'd like to be able to trigger it from a service like: SendMail.new.perform() or some nice one-liner in the controller.
How would I abstract this code away from the controller and how would I call that new service/abstraction?
CodePudding user response:
Twilio SendGrid developer evangelist here.
You can absolutely extract that from your controller, this is normally described as a service object.
I like to keep service objects in the app folder. You can do so by creating the directory app/services. Then create a file for the class, app/services/email_service.rb for example. In that file add the code to send the email, maybe something like this:
class EmailService
def self.call(from:, to:, subject:, content:)
self.new.send_email(from: from, to: to, subject: subject, content:
end
def initialize()
@sendgrid = SendGrid::API.new(api_key: Rails.application.credentials.sendgrid)
end
def send_email(from:, to:, subject:, content:)
from = Email.new(email: from)
to = Email.new(email: to)
content = Content.new(type: 'text/plain', value: content)
mail = Mail.new(from, subject, to, content)
response = @sendgrid.client.mail._('send').post(request_body: mail.to_json)
end
end
You can then call this service from your controller with the one liner:
EmailService.call(from: "[email protected]", to: "[email protected]", subject: "My new email service", content: "It's pretty wonderful")
As a bonus, it's also easier to unit test the EmailService separate to the controller and to mock it out in controller tests.
CodePudding user response:
If you are using rails, you can define it in your environment file and use one line code to send email from your controller.
production.rb
config.action_mailer.delivery_method = :sendmail
# Defaults to:
# config.action_mailer.sendmail_settings = {
# location: '/usr/sbin/sendmail',
# arguments: '-i'
# }
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_options = {from: '[email protected]'}
and in your controller
mail( :to => @user.email,
:subject => 'Thanks for signing up for our amazing app' )
best case for using sendmail is using it with an ActionMailer class. You can look it up at rails documentation.
