13.2 Iteration H2: Integration Tests 12.4 Playtime
Create a mailer
rails generate mailer OrderNotifier received shipped
create app/mailers/order_notifier.rb
invoke erb
create app/views/order_notifier
create app/views/order_notifier/received.text.erb
create app/views/order_notifier/shipped.text.erb
invoke test_unit
create test/functional/order_notifier_test.rb
Edit development configuration
edit config/environments/development.rb
Depot::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
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# 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
# }
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exception on mass assignment protection for ActiveRecord models
config.active_record.mass_assignment_sanitizer = :strict
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
end
Tailor the from address
edit app/mailers/order_notifier.rb
class OrderNotifier < ActionMailer::Base
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_notifier.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_notifier.shipped.subject
#
def shipped
@greeting = "Hi"
mail to: "to@example.org"
end
end
Tailor the confirm receipt email
edit app/views/order_notifier/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_notifier.rb
class OrderNotifier < ActionMailer::Base
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_notifier.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_notifier.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(params[:order])
@order.add_line_items_from_cart(current_cart)
respond_to do |format|
if @order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
OrderNotifier.received(@order).deliver
format.html { redirect_to store_url, notice:
'Thank you for your order.' }
format.json { render json: @order, status: :created,
location: @order }
else
@cart = current_cart
format.html { render action: "new" }
format.json { render json: @order.errors,
status: :unprocessable_entity }
end
end
end
Tailor the confirm shipped email (this time in HTML)
edit app/views/order_notifier/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/functional/order_notifier_test.rb
require 'test_helper'
class OrderNotifierTest < ActionMailer::TestCase
test "received" do
mail = OrderNotifier.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 = OrderNotifier.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
rake db:test:load
ruby -I test test/functional/order_notifier_test.rb
Loaded suite test/functional/order_notifier_test
Started
..
Finished in 1.003389 seconds.
2 tests, 8 assertions, 0 failures, 0 errors, 0 skips
Test run options: --seed 61421