ÕªÒª£ºÔÚ±àдÐèÒª·¢ËÍÓʼþµÄÓ¦ÓÃʱ£¬¿ØÖÆÆ÷ÊǾø²»Äܱ»×èÈûµÄ£¬Òò´ËÒì²½·¢Ëͱز»¿ÉÉÙ¡£ÎªÁËʵÏÖÕâ¸ö;¾¶£¬Óʼþ·¢ËÍ´úÂë±ØÐë´Órequest/responseÖÜÆÚ×ªÒÆµ½¿ÉÒÔÔÚºǫ́Òì²½´¦ÀíµÄ½ø³ÌÖÐÈ¥¡£
¡¾±àÕß°´¡¿Òì²½²âÊÔ×ÜÊÇÒ»¸öºÜ´óµÄÎÊÌ⣬Óʼþ·¢ËͲâÊÔ¸üÊÇÈúܶ࿪·¢Í¬Ñ§²»ÖªµÀ´ÓÄÄÀïÈëÊÖ¡£ÔÚаæµÄRailsÀÕâÀà²âÊÔÔںܴó³Ì¶ÈÉϱ»¼ò»¯ÁË¡£
¹ØÓÚÒëÕߣºÀîÕÜ£¬OneAPM¹¤³Ìʦ£¬ÓµÓÐ7ÄêÒ»Ïß¿ª·¢¾Ñé£¬ÔøÔÚ´óÐÍÃñº½¡¢µçÁ¦µÈÆóÒµ¾ÍÖ°£¬Ñá¾ëÁ˹úÓÐÆóÒµµÄÎÞÁÄ·ÕΧ֮ºó£¬ÒåÎÞ·´¹ËµÄͶ½ø»¥ÁªÍøÆóÒµµÄ´ó³±Ö®ÖС£Æ½Ê±Ï²»¶Ñо¿¸÷ÖÖ±à³ÌÓïÑÔ£¬Ä¿Ç°ÔÚOneAPM¸ºÔðRuby̽ÕëµÄÑз¢£¬Ñо¿RubyÓïÑÔʵÏÖ£¬ÒÔ¼°RubyVMµ×²ãµÄ¼¼Êõ¡£

ÒÔÏÂΪÒëÎÄ
ÔÚ±àдÐèÒª·¢ËÍÓʼþµÄÓ¦ÓÃʱ£¬¿ØÖÆÆ÷ÊǾø²»Äܱ»×èÈûµÄ£¬Òò´ËÒì²½·¢Ëͱز»¿ÉÉÙ¡£ÎªÁËʵÏÖÕâ¸ö;¾¶£¬Óʼþ·¢ËÍ´úÂë±ØÐë´Órequest/responseÖÜÆÚ×ªÒÆµ½¿ÉÒÔÔÚºǫ́Òì²½´¦ÀíµÄ½ø³ÌÖÐÈ¥¡£
ÄÇô£¬Èç´Ë´¦ÀíÖ®ºó£¬´úÂëµÄÕý³£ÔËÐÐÓÖ¸ÄÈçºÎ±£ÕÏ£¿±¾Æª²©ÎÄÖУ¬ÎÒÃǽ«ÖØµã¹Ø×¢²âÊÔµÄ;¾¶£¬Í¬Ê±½«»áʹÓÃMiniTest£¨RailsÒѾÄÚÖÃÁËÕâ¸ö¿ò¼Ü£©£¬µ«ÊÇʹÓõÄÀíÄîÈ´¿ÉÒԺܼòµ¥µØ×ª»»ÎªRspec¡£
ÏÖÔÚÓÐÒ»¸öºÃÏûÏ¢£¬ÄǾÍÊÇ´ÓRails 4.2¿ªÊ¼£¬Òì²½Óʼþ·¢²¼ÒѾ±È֮ǰ¼òµ¥¶àÁË¡£ÎÒÃÇÔÚÀý×ÓÖÐʹÓÃSidekiq×÷Ϊ¶ÓÁÐϵͳ¡£ÓÉÓÚActionMailer#deliver_later½¨Á¢ÔÚActiveJobÖ®ÉÏ£¬½Ó¿Ú·Ç³£µÄ¼ò½àÃ÷ÁË¡£Õâ±íʾ£¬Òª²»ÊÇÎÒ¸Õ²ÅÌáÁËһϣ¬ÉíΪ¿ª·¢Õß»òÓû§µÄÄãÒ²²»»áÖªÇé¡£½¨Á¢¶ÓÁÐϵͳÊÇÁíÍâÒ»¸ö»°Ì⣬Äã¿ÉÒÔÔÚgetting started with Active Job hereÖÐÁ˽â¸ü¶àÏêϸÐÅÏ¢¡£
±ðÌ«ÒÀÀµÐ¡×é¼þ
ÔÚÀý×ÓÖУ¬¼ÙÉèÄãÒѾÕýÈ·ÅäÖÃÁËSidekiq¼°ÆäÒÀÀµ×é¼þ£¬Òò´Ë±¾³¡¾°ÖÐÎ¨Ò»ÌØÓеĴúÂë¾ÍÊÇÉêÃ÷Active Job¸ÃʹÓÃÄÄÒ»¸ö¶ÓÁе÷½ÚÆ÷¡£
# config/application.rb
module OurApp
class Application < Rails::Application
# ...
config.active_job.queue_adapter = :sidekiq
end
end |
Active Job¿ÉÒÔ°ïÖúÓû§´ó·ù¶È±ÜÃâ¶ÓÁÐÅäÖÃϸ½Ú£¬ÔÚResque¡¢Delayed Job»òÆäËû¹¤×÷ÉÏÒ²¿ÉÒÔʹÓá£Òò´Ë£¬Èç¹ûÎÒÃÇת¶øÊ¹ÓÃSucker Punch£¬Î¨Ò»µÄ¸Ä±ä¾ÍÊÇÔÚÒýÓÃÏàÓ¦µÄÒÀÀµ°üºó£¬½«queue_adapter´Ó:sidekiq¸ÄΪ£ºsucker_punch¾Í¿ÉÒÔÁË¡£
Õ¾ÔÚActive JobµÄ¼ç°òÉÏ
Èç¹ûÄã¶ÔRails 4.2»òÕßActive Job²»Ì«Á˽⣬https://blog.engineyard.com/2014/getting-started-with-active-job¿ÉÒÔ°ïÖúÄ㿪ʼ¡£È»¶ø£¬ÕâÆªÎÄÕÂÁô¸øÎÒµÄÒ»¸öСÆÚÐíÊÇ£¬ÕÒµ½Ò»ÖÖ¼ò½à¡¢µØµÀµÄ²âÊÔ·½·¨£¬´Ó¶øÈÃËùÓÐ×é¼þ¶¼ÄÜÕý³£µÄÔËÐС£
¸ù¾Ý±¾ÎĵÄÄ¿±ê£¬ÎÒÃǼٶ¨ÒѾ²¿ÊðÁË£º
- Rails 4.2»òÕßÒ»¸ö¸ü¸ßµÄ°æ±¾
-
ÒѾÉèÖúÃqueue_adapterµÄActive Job (Sidekiq¡¢ResqueµÈ)
-
Ò»·âÓʼþ
ÈκÎÓʼþ¶¼Ó¦¸ÃÄܹ»°´ÕÕÕâÀïÃèÊöµÄ·½Ê½Õý³£¹¤×÷£¬ÕâÀïÎÒÃǾÍÓÃÒ»·â»¶ÓÓʼþÀ´Ê¹Õâ¸öÀý×Ó¸üʵÓãº
#app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default from: 'email@example.com'
def welcome_email(user:)
mail(
to: user.email,
subject: "Hi #{user.first_name}, and welcome!"
)
end
end |
ΪÁ˱£³Ö³ÌÐò¼òµ¥²¢ÓÐÕë¶ÔÐÔ£¬ÕâÀï»áÔÚÿ¸öÓû§×¢²áºó·¢Ë͸øËûÃÇÒ»·â»¶ÓÓʼþ¡£
ÕâºÍthe Rails guides mailer exampleÊÇÒ»ÑùµÄ£º
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
# Yes, Ruby 2.0+ keyword arguments are preferred
UserMailer.welcome_email(user: @user).deliver_later
end
end |
The Mailer Should Do Its Job, Eventually
½ÓÏÂÀ´£¬ÎÒÃÇÏëÈ·±£¿ØÖÆÆ÷ÄÚµÄÈÎÎñÄÜÈçËùÆÚ´ýµÄÄÇÑùÖ´ÐС£
ÔÚ²âÊÔÖ¸ÄÏÖУ¬custom assertions for testing jobs inside other componentsµÄÕ½ڽéÉÜÁË´óÔ¼ÁùÖÖÕâÑùµÄ×Ô¶¨Òå¶ÏÑÔ·½·¨¡£
»òÐíÖ±¾õ¸æËßÄãÓ¦¸Ãµ¥µ¶Ö±È룬ȻºóʹÓÃassert_enqueued_jobsassert-enqueued-jobsÀ´²âÊÔÿ´ÎÌí¼ÓÐÂÓû§Ê±£¬ÎÒÃÇÓзñ½«Óʼþ´«ËÍÈÎÎñ·ÅÈë¶ÓÁС£
Äã¿ÉÄÜ»áÕâô×ö£º
# test/controllers/users_controller_test.rb
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
test 'email is enqueued to be delivered later' do
assert_enqueued_jobs 1 do
post :create, {}
end
end
end |
È»¶øÈç¹ûÕâô×ö£¬Äã»á¾ªÆæµØ·¢ÏÖ²âÊÔʧ°ÜÁË£¬ÏµÍ³»á¸æËßÄãassert_enqueued_jobsδ¾¶¨Ò壬ÇÒÎÞ·¨Ê¹Óá£
ÕâÊÇÒòΪ£¬ÎÒÃǵIJâÊÔÀà¼Ì³Ð×ÔActionController::TestCase£¬¶øºóÕßÔÚ±àдʱûÓаüº¬ActiveJob::TestHelper¡£
²»¹ýÎÒÃǺܿì¾Í¿ÉÒÔÐÞÕýÕâÒ»µã£º
# test/test_helper.rb
class ActionController::TestCase
include ActiveJob::TestHelper
end |
¼Ù¶¨ÎÒÃǵĴúÂëÈçÆÚÖ´ÐУ¬ÄÇô²âÊÔÓ¦¸Ã¾ÍÄÜ˳Àûͨ¹ýÁË¡£
ÕâÊǺÃÏûÏ¢¡£ÏÖÔÚ£¬ÎÒÃÇ¿ÉÒÔÖØ¹¹ÎÒÃǵĴúÂ룬Ôö¼ÓÐµĹ¦ÄÜ£¬Ò²¿ÉÒÔÔö¼ÓеIJâÊÔ¡£ÎÒÃÇ¿ÉÒÔÑ¡ÔñºóÕߣ¬¿´¿´ÎÒÃǵÄÓʼþÓзñͶµÝ³É¹¦£¬Èç¹ûÊǵϰ£¬ÄǾͼì²éͶµÝµÄÄÚÈÝÊÇ·ñÕýÈ·¡£
ActionMailerÄÜΪÎÒÃÇÌṩһ¸ö°üº¬ËùÓз¢³öÓʼþµÄ¶ÓÁУ¬Ç°ÌáÊǽ«delivery_methodÑ¡ÏîÉèÖÃΪ£ºtest£¬ÎÒÃÇÄÜͨ¹ýActionMailer::Base.deliveries¶ÁÈ¡Õâ¸ö¶ÓÁС£
ÔÚͬ²½Í¶µÝÓʼþʱ£¬¼ì²âÓʼþÊÇ·ñ·¢Ëͳɹ¦ÊǺÜÈÝÒ׵ġ£ÎÒÃÇÖ»Ðè¼ì²éÔÚ¶¯×÷Íê³Éºó£¬Í¶µÝ¼ÆÊýÆ÷¼Ó1¡£ÓÃMiniTestÀ´Ð´µÄ»°£¬¾ÍÏñÏÂÃæÕâÑù£º
assert_difference 'ActionMailer::Base.deliveries.size', +1 do post :create, {} end |
ÎÒÃǵIJâÊÔÊÇʵʱ·¢ÉúµÄ£¬µ«ÔÚ¿ªÆª¾ÍÒѾ֪µÀ²»ÄÜ×èÀ¹¿ØÖÆÆ÷£¬ÐèÒªÔÚºǫ́½ø³ÌÖз¢ËÍÓʼþ£¬ÏÖÔÚÎÒÃǰÑËùÓеÄ×é¼þ¶¼×é×°ÆðÀ´£¬È·¶¨ÏµÍ³ÊÇûÓÐÎÊÌâµÄ¡£Òò´Ë£¬ÔÚÒì²½µÄÊÀ½çÀÎÒÃDZØÐëÏÈÖ´ÐÐËùÓжÓÁÐÖеÄÈÎÎñÔÙÈ¥Åж¨Ö´Ðнá¹û¡£ÎªÁËÖ´ÐÐpendingÖеÄActive JobÈÎÎñ£¬ÎÒÃÇʹÓÃperform_enqueued_jobs£º
test 'email is delivered with expected content' do perform_enqueued_jobs do post :create, {} delivered_email = ActionMailer::Base.deliveries.last
# assert our email has the expected content, e.g.
assert_includes delivered_email.to, @user.email
end
end |
Ëõ¶Ì·´À¡Á÷³Ì
ĿǰΪֹ£¬ÎÒÃǶ¼ÔÚ½øÐй¦ÄÜÐÔ²âÊÔÒÔÈ·±£ÎÒÃǵĿØÖÆÆ÷ÈçÆÚÖ´ÐС£µ«ÊÇ£¬´úÂëµÄ±ä»¯×ãÒÔÆÆ»µÎÒÃÇ·¢Ë͵ÄÓʼþ£¬ÎªÊ²Ã´²»¶ÔÎÒÃǵÄÓʼþ³ÌÐò½øÐе¥Ôª²âÊÔ£¬´Ó¶øËõ¶Ì·´À¡Á÷³Ì£¬È»ºó¸ü¿ìµØ¶´²ì±ä»¯ÄØ£¿
Rails²âÊÔÖ¸ÄϽ¨ÒéÔÚÕâÀïʹÓÃfixtures£¬µ«ÊÇÎÒ¾õµÃËûÃÇÌ«ÉúÓ²ÁË¡£ÓÈÆäÊÇÒ»¿ªÊ¼£¬µ±ÎÒÃÇ»¹ÔÚ³¢ÊÔÉè¼ÆÓʼþʱ£¬¿ìËٱ仯¾Í»áÈÃËûÃDZäµÃ²»¿ÉÓã¬ÈÃÎÒÃǵIJâÊÔÎÞ·¨Í¨¹ý¡£ÎÒÆ«ÏòʹÓÃassert_matchÒÔ¹Ø×¢ÄÇЩ¹¹³ÉÓʼþÖ÷ÌåµÄ¹Ø¼üÔªËØ¡£
Ϊ´Ë£¬Ò²ÒòΪÆäËûÔÒò£¨±ÈÈç³éÀë´¦Àí¶à²¿·ÖÓʼþµÄÂß¼½á¹¹£©£¬ÎÒÃÇ¿ÉÒÔ½¨Á¢×Ô¶¨Òå¶ÏÑÔ¡£Õâ¿ÉÒÔÀ©Õ¹MiniTest±ê×¼¶ÏÑÔ»òRailsרÊô¶ÏÑÔ¡£ÕâÒ²ÊÇ´´½¨×Ô¼ºµÄÁìÓòרÊôÓïÑÔ£¨Domain Specific Language£©²¢ÓÃÓÚ²âÊԵĺÃÀý×Ó¡£
ÈÃÎÒÃÇÔÚ²âÊÔÒ»Îļþ¼ÐÄÚ´´½¨Ò»¸ö¹²ÏíÎļþ¼Ð£¬ÓÃÒÔ´æ·ÅSharedMailerTestsÄ£¿é¡£ÎÒÃÇ×Ô¶¨ÒåµÄ¶ÏÑÔ¿ÉÒÔÕâôÀ´Ð´£º
# /test/shared/shared_mailer_tests.rb module SharedMailerTests def assert_email_body_matches(matcher:, email:) if email.multipart? %w(text html).each do |part| assert_match matcher, email.send("#{part}_part").body.to_s end else assert_match matcher, email.body.to_s end end end |
½ÓÏÂÀ´£¬ÎÒÃÇÐèÒªÈÃÓʼþ²âÊÔϵͳעÒâµ½Õâ¸ö×Ô¶¨Òå¶ÏÑÔ£¬Îª´Ë£¬ÎÒÃÇ¿ÉÒÔ½«Æä·ÅÈëActionMailer::TestCaseÀàÖС£È»ºó¿ÉÒÔ½è¼øÖ®Ç°°ÑActiveJob::TestHelperÀà°üº¬ÓÚActionController::TestCaseÀàµÄ·½·¨£º
# test/test_helper.rb
require 'shared/shared_mailer_tests'
class ActionMailer::TestCase
include SharedMailerTests
end |
×¢Ò⣬ÎÒÃÇÊ×ÏÈÐèÒªÔÚtest_helperÖÐrequire shared_mailer_tests¡£
ÕâЩ°ìºÃÖ®ºó£¬ÎÒÃÇÏÖÔÚ¿ÉÒÔÈ·ÐÅÎÒÃǵÄÓʼþÖаüº¬ÎÒÃÇÆÚÍûµÄ¹Ø¼üÔªËØ¡£¼ÙÉèÎÒÃÇÏëÈ·±£·¢Ë͸øÓû§µÄURL°üº¬Ò»Ð©ÓÃÓÚ×·×ÙµÄÌØ¶¨UTM²ÎÊý¡£ÎÒÃÇÏÖÔÚ¿ÉÒÔ½«×Ô¶¨Òå¶ÏÑÔÓëÀÏÅóÓÑperform_enqueued_jobsÁªºÏÆðÀ´Ê¹Ó㬾ÍÏñÕâÑù£º
# test/mailers/user_mailer_test.rb
class ToolMailerTest < ActionMailer::TestCase
test 'emailed URL contains expected UTM params' do
UserMailer.welcome_email(user: @user).deliver_later
perform_enqueued_jobs do
refute ActionMailer::Base.deliveries.empty?
delivered_email = ActionMailer::Base.deliveries.last
%W(
utm_campaign=#{@campaign}
utm_content=#{@content}
utm_medium=email
utm_source=mandrill
).each do |utm_param|
assert_email_body_matches utm_param, delivered_email
end
end
end |
½áÂÛ
ÔÚActive JobµÄ»ù´¡ÉÏ£¬Ê¹ÓÃActionMailerÈôÓͬ²½·¢ËÍÓʼþµ½Í¨¹ý¶ÓÁз¢ËÍÓʼþµÄת»¯±äµÃÈç´Ë¼òµ¥£¬¾ÍÈçͬ´Ódeliver_nowת»¯µ½deliver_later¡£
ͬʱ£¬ÓÉÓÚʹÓÃActive Job´ó´ó¼ò»¯ÁËÉ趨¹¤×÷»ù´¡»·¾³µÄÁ÷³Ì£¬Äã¿ÉÒÔ¶Ô×Ô¼ºËùÓõĶÓÁÐϵͳ֪֮ÉõÉÙ¡£Ï£ÍûÕâÆª½Ì³ÌÄÜÈÃÄã¶Ô´Ë¹ý³ÌÓиü¶àÁ˽⡣
Ó¢ÎÄÔÎÄ£ºTesting async emails, the Rails 4.2+ way
|