14.2 Iteration I2: Integration Tests 12.5 Playtime
Create a mailer
rails generate mailer Order received shipped
create app/mailers/order_mailer.rb
invoke erb
create app/views/order_mailer
identical app/views/layouts/mailer.text.erb
identical app/views/layouts/mailer.html.erb
create app/views/order_mailer/received.text.erb
create app/views/order_mailer/received.html.erb
create app/views/order_mailer/shipped.text.erb
create app/views/order_mailer/shipped.html.erb
invoke test_unit
create test/mailers/order_mailer_test.rb
create test/mailers/previews/order_mailer_preview.rb
Edit development configuration
edit config/environments/development.rb
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports.
config.consider_all_requests_local = true
# Enable/disable caching. By default caching is disabled.
if Rails.root.join('tmp/caching-dev.txt').exist?
config.action_controller.perform_caching = true
config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => 'public, max-age=172800'
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# Don't actually send emails
config.action_mailer.delivery_method = :test
#
# Alternate configuration example, using gmail:
# config.action_mailer.delivery_method = :smtp
# config.action_mailer.smtp_settings = {
# address: "smtp.gmail.com",
# port: 587,
# domain: "domain.of.sender.net",
# authentication: "plain",
# user_name: "dave",
# password: "secret",
# enable_starttls_auto: true
# }
config.action_mailer.perform_caching = false
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
# Suppress logger output for asset requests.
config.assets.quiet = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
# Use an evented file watcher to asynchronously detect changes in source code,
# routes, locales, etc. This feature depends on the listen gem.
# config.file_watcher = ActiveSupport::EventedFileUpdateChecker
end
Tailor the from address
edit app/mailers/order_mailer.rb
class OrderMailer < ApplicationMailer
default from: 'Sam Ruby <depot@example.com>'
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.order_mailer.received.subject
#
def received
@greeting = "Hi"
mail to: "to@example.org"
end
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.order_mailer.shipped.subject
#
def shipped
@greeting = "Hi"
mail to: "to@example.org"
end
end
Tailor the confirm receipt email
rm app/views/order*/received.html.erb
edit app/views/order_mailer/received.text.erb
Dear <%= @order.name %>
Thank you for your recent order from The Pragmatic Store.
You ordered the following items:
<%= render @order.line_items -%>
We'll send you a separate e-mail when your order ships.
Text partial for the line items
edit app/views/line_items/_line_item.text.erb
<%= sprintf("%2d x %s",
line_item.quantity,
truncate(line_item.product.title, length: 50)) %>
Get the order, sent the confirmation
edit app/mailers/order_mailer.rb
class OrderMailer < ApplicationMailer
default from: 'Sam Ruby <depot@example.com>'
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.order_mailer.received.subject
#
def received(order)
@order = order
mail to: order.email, subject: 'Pragmatic Store Order Confirmation'
end
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.order_mailer.shipped.subject
#
def shipped(order)
@order = order
mail to: order.email, subject: 'Pragmatic Store Order Shipped'
end
end
Invoke mailer from the controller
edit app/controllers/orders_controller.rb
def create
@order = Order.new(order_params)
@order.add_line_items_from_cart(@cart)
respond_to do |format|
if @order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
session[:order_id] = @order.id
OrderMailer.received(@order).deliver_later
format.html { redirect_to store_index_url, notice:
'Thank you for your order.' }
format.json { render :show, status: :created,
location: @order }
else
format.html { render :new }
format.json { render json: @order.errors,
status: :unprocessable_entity }
end
end
end
Tailor the confirm shipped email (this time in HTML)
rm app/views/order_mailer/shipped.text.erb
edit app/views/order_mailer/shipped.html.erb
<h3>Pragmatic Order Shipped</h3>
<p>
This is just to let you know that we've shipped your recent order:
</p>
<table>
<tr><th colspan="2">Qty</th><th>Description</th></tr>
<%= render @order.line_items -%>
</table>
Review HTML partial for the line items
edit app/views/line_items/_line_item.html.erb
<% if line_item == @current_item %>
<tr id="current_item">
<% else %>
<tr>
<% end %>
<td><%= line_item.quantity %>×</td>
<td><%= line_item.product.title %></td>
<td class="item_price"><%= number_to_currency(line_item.total_price) %></td>
</tr>
Update the test case
edit test/mailers/order_mailer_test.rb
require 'test_helper'
class OrderMailerTest < ActionMailer::TestCase
test "received" do
mail = OrderMailer.received(orders(:one))
assert_equal "Pragmatic Store Order Confirmation", mail.subject
assert_equal ["dave@example.org"], mail.to
assert_equal ["depot@example.com"], mail.from
assert_match /1 x Programming Ruby 1.9/, mail.body.encoded
end
test "shipped" do
mail = OrderMailer.shipped(orders(:one))
assert_equal "Pragmatic Store Order Shipped", mail.subject
assert_equal ["dave@example.org"], mail.to
assert_equal ["depot@example.com"], mail.from
assert_match /<td>1×<\/td>\s*<td>Programming Ruby 1.9<\/td>/,
mail.body.encoded
end
end
rails test test/mailers/order_mailer_test.rb
Run options: --seed 57102
# Running:
..
Finished in 0.424261s, 4.7141 runs/s, 23.5704 assertions/s.
2 runs, 10 assertions, 0 failures, 0 errors, 0 skips