Enviando E-mails de Confirmação de Pedido no Rails com ActionMailer - Parte 1
Enviar e-mails é uma funcionalidade comum em aplicações web. No Ruby on Rails, o ActionMailer
é uma ferramenta poderosa para lidar com o envio de e-mails. Vamos explorar como utilizá-lo para enviar e-mails de confirmação de pedidos e como testar essa funcionalidade.
Informações básicas
Configuração do Ambiente de Testes
- Adicione as gems necessárias ao seu
Gemfile
:
group :development, :test do
gem 'rspec-rails'
gem 'shoulda-matchers'
gem 'email_spec'
gem 'letter_opener'
end
- Execute
bundle install
. - Configure o RSpec e o Shoulda Matchers em
spec/rails_helper.rb
:
require 'email_spec'
require 'email_spec/rspec'
RSpec.configure do |config|
config.include(EmailSpec::Helpers)
config.include(EmailSpec::Matchers)
end
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
Configuração do Ambiente de Desenvolvimento
- Em
config/environments/development.rb
, configure oletter_opener
:
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.perform_deliveries = true
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
config.action_mailer.delivery_method = :letter_opener
Esta linha define o método de entrega dos e-mails para:letter_opener
. O Letter Opener é uma gem usada principalmente em ambientes de desenvolvimento para visualizar e-mails enviados pela aplicação sem a necessidade de enviá-los realmente através de um serviço SMTP. Quando um e-mail é enviado, o Letter Opener abre uma nova aba no navegador padrão exibindo o conteúdo do e-mail. Isso é útil para desenvolvedores testarem e visualizarem e-mails durante o desenvolvimento.config.action_mailer.perform_deliveries = true
Esta configuração determina se os e-mails serão realmente enviados. Quando definido comotrue
, o ActionMailer tentará enviar e-mails. Se definido comofalse
, o ActionMailer não enviará e-mails, mas irá simular o envio. Isso pode ser útil em certos ambientes (como testes) onde você não quer que os e-mails sejam realmente enviados.config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
Esta linha define as opções padrão de URL para o ActionMailer. Ohost
e aport
especificados aqui são usados para gerar URLs completas nos e-mails, como links para redefinição de senha ou confirmação de conta. No exemplo dado, o host está definido comolocalhost
e a porta como3000
, que são os valores padrão para um servidor Rails em desenvolvimento. Isso significa que qualquer link gerado nos e-mails apontará parahttp://localhost:3000
. Em um ambiente de produção, você substituiria esses valores pelo domínio real e pela porta (se aplicável) do seu aplicativo.
Criando o Mailer com ActionMailer
- Gere o Mailer:
rails g mailer OrderMailer
- Defina o método de envio no
app/mailers/order_mailer.rb
:
class OrderMailer < ApplicationMailer
def order_confirmation(user, order)
@user = user
@order = order
mail(to: @user.email, subject: 'Order Confirmation')
end
end
Criando a View do Mailer
- Crie
app/views/order_mailer/order_confirmation.html.erb
.
<!DOCTYPE html>
<html>
<head>
<title>Order Confirmation</title>
</head>
<body>
<h1>Order Confirmation</h1>
<p>
Hello <%= @user.name %>,
</p>
<p>
Thank you for your order. We are currently processing your order and will send you a confirmation once it is shipped.
</p>
<p>
Order Details:
<% @order.items.each do |item| %>
<div>
<%= item.name %> - <%= item.quantity %>
</div>
<% end %>
</p>
<p>
If you have any questions, please contact us at [email protected].
</p>
</body>
</html>
Neste exemplo, a view do e-mail inclui uma saudação personalizada com o nome do usuário e uma mensagem de agradecimento, que são os requisitos dos nossos testes. Além disso, adicionei detalhes do pedido e informações de contato para tornar o e-mail mais informativo e útil para o usuário.
Nota: Certifique-se de que as variáveis @user
e @order
estejam sendo corretamente definidas no método order_confirmation
do seu OrderMailer
. Por exemplo:
Escrevendo Testes
- Crie
spec/mailers/order_mailer_spec.rb
para testar o mailer.
require "rails_helper"
RSpec.describe OrderMailer, type: :mailer do
let(:user) { create(:user) }
let(:order) { create(:order, user: user) }
describe 'order_confirmation' do
let(:mail) { OrderMailer.order_confirmation(user, order) }
it 'renders the headers' do
expect(mail.subject).to eq('Order Confirmation')
expect(mail.to).to eq([user.email])
expect(mail.from).to eq(['[email protected]'])
end
it 'renders the body' do
expect(mail.body.encoded).to match("Hello #{user.name},")
expect(mail.body.encoded).to match("Thank you for your order.")
end
end
end
OrderMailer Spec
- Testa se o assunto, destinatário e remetente do e-mail estão corretos.
- Verifica se o corpo do e-mail contém as informações esperadas.
Enviando o E-mail na Aplicação
- No ponto da aplicação onde o pedido é finalizado, adicione:
OrderMailer.order_confirmation(user, order).deliver_later
Diferença entre usar e não usar ActionMailer
O ActionMailer
é uma parte integrante do Rails que simplifica o envio de e-mails. Sem ele, você teria que manualmente configurar SMTP, lidar com a renderização de templates e gerenciar a lógica de envio. Com ActionMailer
, você obtém:
- Integração fácil com templates de e-mail.
- Gerenciamento simplificado de configurações de envio.
- Suporte para envio assíncrono e sincronizado.
- Facilidade para testar e-mails.
O ActionMailer
é uma ferramenta essencial no Rails para o envio de e-mails, simplificando o processo e permitindo que você se concentre mais na lógica do negócio e menos na infraestrutura de envio de e-mails. Este post cobriu como configurar, enviar e testar e-mails de confirmação de pedidos usando ActionMailer
.
Porém, há algo que precisamos melhorar! Pensa comigo, é importante que o usuário receba o email imediantamente? ou essa operação poderia tranquilamente levar alguns segundos ou até 2 minutos mais ou menos, o que pensa? É isso que precisamos melhorar.
Referências
Documentação oficial do ActionMailer: Action Mailer Basics