active_waiter 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +93 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/active_waiter/application.js +16 -0
- data/app/assets/stylesheets/active_waiter/application.css +15 -0
- data/app/controllers/active_waiter/application_controller.rb +4 -0
- data/app/controllers/active_waiter/jobs_controller.rb +36 -0
- data/app/helpers/active_waiter/application_helper.rb +4 -0
- data/app/views/active_waiter/jobs/_reload.html.erb +3 -0
- data/app/views/active_waiter/jobs/error.html.erb +6 -0
- data/app/views/active_waiter/jobs/link_to.html.erb +12 -0
- data/app/views/active_waiter/jobs/progress.html.erb +6 -0
- data/app/views/active_waiter/jobs/show.html.erb +6 -0
- data/app/views/layouts/active_waiter/application.html.erb +24 -0
- data/config/routes.rb +4 -0
- data/lib/active_waiter.rb +25 -0
- data/lib/active_waiter/engine.rb +5 -0
- data/lib/active_waiter/job.rb +28 -0
- data/lib/active_waiter/version.rb +3 -0
- data/lib/tasks/waiter_tasks.rake +4 -0
- data/test/active_waiter/job_test.rb +40 -0
- data/test/controllers/active_waiter/jobs_controller_test.rb +87 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +31 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +44 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/log/test.log +6847 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/tmp/cache/53A/930/waiter%3Ahello +1 -0
- data/test/dummy/tmp/cache/54D/5C0/result%3Ahello +1 -0
- data/test/dummy/tmp/cache/623/7D0/progress%3Ahello +1 -0
- data/test/dummy/tmp/cache/815/000/active_waiter%3Ahello +2 -0
- data/test/dummy/tmp/cache/BC3/BB0/result%3A5476b414-8387-40bf-ae81-16f86a204581 +1 -0
- data/test/dummy/tmp/cache/BC6/630/result%3Adb3970e5-755d-4810-b660-d0b236826957 +1 -0
- data/test/dummy/tmp/cache/C32/BF0/result%3Af72e8b8d-512c-4819-a041-44877487cd7e +1 -0
- data/test/dummy/tmp/cache/C54/560/result%3Aa9598b7d-67f5-4253-a0c4-2035e567b4bc +1 -0
- data/test/dummy/tmp/cache/C61/C50/result%3A976614ea-ea80-4087-b8cc-e5f73f776503 +1 -0
- data/test/dummy/tmp/cache/C62/DE0/result%3A50288cd0-9cf2-4c5b-96b9-0458cf56e548 +1 -0
- data/test/dummy/tmp/cache/C74/C10/result%3Ae5bb8515-3939-4ef4-968b-a7f7d9d79273 +1 -0
- data/test/dummy/tmp/cache/C87/CE0/result%3A4af5f188-795f-476e-acbf-51208e17f030 +1 -0
- data/test/dummy/tmp/cache/C99/C60/progress%3A5476b414-8387-40bf-ae81-16f86a204581 +1 -0
- data/test/dummy/tmp/cache/C9C/6E0/progress%3Adb3970e5-755d-4810-b660-d0b236826957 +1 -0
- data/test/dummy/tmp/cache/CAE/6D0/result%3Abd42513f-7484-4dac-a91f-e00e398fd811 +1 -0
- data/test/dummy/tmp/cache/CB3/BF0/result%3Afda8e964-d054-48d8-8c0c-100d5736ae6b +1 -0
- data/test/dummy/tmp/cache/CB9/930/result%3A55536147-f9cd-42ba-8df2-f1b62f6af737 +1 -0
- data/test/dummy/tmp/cache/CC0/260/result%3A16ff29ac-f5ad-4397-a60f-64ae9917d573 +1 -0
- data/test/dummy/tmp/cache/CE4/110/result%3A35ee268a-c31f-4f47-87ee-cc1fa8622e13 +1 -0
- data/test/dummy/tmp/cache/D08/CA0/progress%3Af72e8b8d-512c-4819-a041-44877487cd7e +1 -0
- data/test/dummy/tmp/cache/D2A/610/progress%3Aa9598b7d-67f5-4253-a0c4-2035e567b4bc +1 -0
- data/test/dummy/tmp/cache/D2B/DC0/result%3Ad20d41eb-75cf-4bc0-b338-eb14e6e0e3d2 +1 -0
- data/test/dummy/tmp/cache/D33/5A0/result%3A16b07abb-16b1-4e4d-92b9-3dfd8bda18e2 +1 -0
- data/test/dummy/tmp/cache/D37/D00/progress%3A976614ea-ea80-4087-b8cc-e5f73f776503 +1 -0
- data/test/dummy/tmp/cache/D38/E90/progress%3A50288cd0-9cf2-4c5b-96b9-0458cf56e548 +1 -0
- data/test/dummy/tmp/cache/D4A/CC0/progress%3Ae5bb8515-3939-4ef4-968b-a7f7d9d79273 +1 -0
- data/test/dummy/tmp/cache/D5D/D90/progress%3A4af5f188-795f-476e-acbf-51208e17f030 +1 -0
- data/test/dummy/tmp/cache/D6C/2A0/result%3Afc8752e1-ead1-433f-af5c-f5c86cd2b1e3 +1 -0
- data/test/dummy/tmp/cache/D74/9E0/result%3A91eb5c23-5fc6-4c4f-a183-ccb1edeee859 +1 -0
- data/test/dummy/tmp/cache/D84/780/progress%3Abd42513f-7484-4dac-a91f-e00e398fd811 +1 -0
- data/test/dummy/tmp/cache/D89/CA0/progress%3Afda8e964-d054-48d8-8c0c-100d5736ae6b +1 -0
- data/test/dummy/tmp/cache/D8F/9E0/progress%3A55536147-f9cd-42ba-8df2-f1b62f6af737 +1 -0
- data/test/dummy/tmp/cache/D96/310/progress%3A16ff29ac-f5ad-4397-a60f-64ae9917d573 +1 -0
- data/test/dummy/tmp/cache/DBA/1C0/progress%3A35ee268a-c31f-4f47-87ee-cc1fa8622e13 +1 -0
- data/test/dummy/tmp/cache/E01/E70/progress%3Ad20d41eb-75cf-4bc0-b338-eb14e6e0e3d2 +1 -0
- data/test/dummy/tmp/cache/E09/650/progress%3A16b07abb-16b1-4e4d-92b9-3dfd8bda18e2 +1 -0
- data/test/dummy/tmp/cache/E42/350/progress%3Afc8752e1-ead1-433f-af5c-f5c86cd2b1e3 +1 -0
- data/test/dummy/tmp/cache/E4A/A90/progress%3A91eb5c23-5fc6-4c4f-a183-ccb1edeee859 +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/-FKgYemgnLPloA8L9_uc-qSP9Csz8KJeFy9-9tNbTYE.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/-htuxusII34GUEa1Y1dhHlPMREKFFP0I9an-0fPai1Y.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/0Lwyq9p8qx-NPHj2mBzAXHqSLjbAHDtNbuEcaVsLptI.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/0e8ZJThcO34GZamk_QI5PgGHebcQ_Pg-lz0uqaXHT4E.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/12TsG6XcaV1lKbmxnQVLDp8rypRI35yC0kFTDEj-sBs.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/1JbLVPcYaKgFjstM5eOonLAWxk_zH78g94H5Y_zoHaY.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/1eZUUEinxr0XtcAQd2B4BuriiH8qNhiC0CttyzvyRCY.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/1i1op13Ae3Pv4k56iSw0YYG1lOQbc3XOBK3M_74-INY.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/1k7k_fcUk4-GoIHaNQHejiRVZl-Pnd7vFXtQSTJGOho.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/29tZrgfzuQRuwLaDKo1dFqObg71vcVS6kAK_QUP-MRE.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/2KG4HBSny8fUdnEqQVLHtl23H1QLtJLhqxrHD340nrc.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/2LUFqOewM3gnSHBnnPjlZCvuLOt2pIESv58AQV__tFo.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/35hQ1jprgNu7eqmxxZIEldbtZXA7SK8F4B0jgYHdl-Q.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/4EbIxUrr6TrMPFW6Oo6PAq9UGP8F6FTQQCLXXdoSC7A.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/4rba5VAhpWBaRrigVIoX3CMVH_mr5S0J1HOhSA1fDQA.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/5GH1Olvcwf17EORgb5bg_80CxlVWqdDw0dLCIdDsWgk.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/5kF0rdn73jq7uGVfOkWCPEBcG4ZuxVlPySU7dGvT9PI.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/6Yn3BKylqtbKOzQ9C4PQ5zE0ZhFna75Q4nQv2y0UpgQ.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/7AuLNboANu8sU933nvR-LmFqEaIA2TE6qgVWDl7MfOU.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/ASrpInr95Fmk3jRbvXIv6pt3614NTBV0qzwJZ9ccyII.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/B42UCwrGRs5FidWNj3E_UVOJZNiGpMEzZTheP7lo8Ps.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/BuowtxnNzNFEmv6-Xj9DnLTC5Wg0_MXHBvrawKMOhLI.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/C5Q9UkNcSexVplLeGzOXZr7Y2PXFwkXLIxYkWRvaNMY.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/CMOXd13SQ0QgIVsZR3YQeHh3O8Flqgzy-JsjAMOzC_w.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/C__9PeOYhrXzvcJuD4LBB7zfGKFtltFa79hylHbWTXw.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/DodvXIBv4hgxwicUQdrUH7nu0904rqnKgWTgx2kbHI4.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/E8041y9C4S50ps7cHRzwXZGBtxW86O52h_mWkRAeIJA.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/El1vW7N-xrMuF8JBdzfXaGmrBhfZcL2fN6ZISaFVfYw.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Fzx-E_HUicjxUBt89DMz0WBFKFtCzo6x7eN7sLMdXxc.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/G-lodG1Jka671AODJnGT2D_KpCDYMF23db8C-Ha4GJk.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/GKf1Y0SlVRCvDyThY-zOzdxO2HqIAoEjrYQNxuqpIzI.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/IXeCSGIZR6GzJ9FdCIKJrhEaFk80fguISCBirw3jC34.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/IbJ7BoE7lzLfA0j5vC9WYFWJDilBSEJzcRscE8waoeM.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/JSGYqW-UHL6e6RNTmfohq4-cry4P7TMWxaFwnVAVVxg.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/JaYRkmobWLox6QvYvDet0yRB2bh_Y0gCTZX5pLIkmK4.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Jn9oLambmcCsbyxuo-yOUhxeT_QrKjkkmC1RXO13AFM.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/K5XMSe6izrRbQ9YN5FSSrShUn6JkCrheJrfYPnNkGMQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/N5ZMYm5OswvLSgQ_AVMivRPNcsmnfelrUvHNLwtiQLU.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Nw_SGAnCeXZPfX43BQoj5xalMKODjLSfAmeEey5yIgQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/Oxshe88CWlagLX7crM67D-Eritvs_WkP-obQrcgFAgA.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/PRLOxeuiC_y0aNo0xmkcbOxY4KFVJOXzZF2eOvtosoo.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/SL3Dd3REfpOyQp5wOrm1VEK2afLWvUot5TsIuEgdKz8.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/SkvA-zkM5fiG_Z3m4xSBnOMN0t0MfDg2U61j6azwess.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/TBNBkl_ZOLQDtv-gF1D9uvkq8bS6Gq_vZxAMHVTS050.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/TUZA45lyJBN3k4Aue4bBuj0hy67ZU1LBHiGSlNBtQWI.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/UQsWaS8SdBZawmxULjtQ4LKlQISQwQNvLaP-JZxDfwA.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/VOp0pIv_pTt1jyD5JQn5Ee721CyQFQTGdnz4ODw38i4.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/VzJx82ecMrJphuCCeiKWdDlGeylJJOwwaW09VFmZB3o.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/W4U-CePEC2ibeKajQoPowD7fNNoNHOGQKaMrtYyHkoY.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/W6SWsBkl4GgPWdz_vi7v9WtOuH3GLVJ6PaO_KoCsJ5Y.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/XVCtbPtjn02Czn4Q63QqJFs2UBTG0J31UJis5NC53TA.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/YzWqeojadVEyPKiS_1cXuTsQI_nBqoyudANUPEeT7iI.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/c-ws04jyEpjpgrAM4OdXB0x0qW4Ep95GQK5fbF2T01Q.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/d1tT5anqym_5U_MyM1RiPU8QzUSlrSpLlcLOwH97z-c.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/dxjsm7OjfSnkDTyVe4gy-or9j9-Qs5A7ubSilTokIEI.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/eqwweAC_8mWnErE-TujdV4BxweHy1WNLbWj2YidR-ZY.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/gTt4YDzVktx4phYuvI3nYi03tVIdHtgz7xE0z7RCSgE.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/h5QBK-or8YaALTEoyqFHZz2VeHEPDCHp73cpS6_tNDo.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/hgNUJ9G6XRgrtvRqHLiLvK0QJr3q2tUlX5JeK2SLheM.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/hhBSpRKMFrogXpJ1r8m53q-3gHdfEzh-HtSswRlFsrY.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/hn9puRfcK2PWlIceCkiVNetEiEiZI_Xaq2mmYFpZMJc.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/izPiTwUCbh9tpfMATrY5pCxFHFL43Uu0WOf_kGoMTNs.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/k3IFF3lBYfhNvTJ0PAGS2rIgRVgqjIaOHEcaFCGXURM.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/kLLMXTC-18NrDRsqntkF7ARIQvfhoxsA30wuspwxBTQ.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/l0Csu8J1O507Eq8qu4LdcN__P6XPTn993bEXlWzBL3g.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/lDkv8BcV-iihUA36K3Ab-62Gfk9ZYxpiDsx1QQLn3us.cache +3 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/lME5t2GT7fpXK4W11EYQWhLcGccGkaJYLdbsba2VPjg.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/lQbWXQg4tKjoJ8PqCmsJ4ulo_8K4f6Q0k--85ma6W3M.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/oRe84XQAcuwON-4A4JZ_8kwLG1VcUKHgXgoV_JDFQ28.cache +3 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/oTDuis4oHgPfw4tzdw_hYlQngc-fB51xu6-WN8m64u0.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/oTtT66b4H6sUVGlcSiQzW3gyflWZAX5N8wkTJX_daz8.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/p-yWOgy4KbA5EUfA7Q29zG7YO6SltgK2elQKrX5F2Gw.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/p89pJmdIHJvvuTTbcO6MlN77ioNCEuT5SvpKRPiWEZQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/ph5en-XzdEV6YDijatKQkcYBqeFzMb2JDIzs0Qc8EQo.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/q4BTUSEQuQqrn5MVI602Bk8jfNEiIMiY9bwtc_3JyeY.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/q87JrLqyTCkCQuUF--CLYabb86fA_x_QAOV9IwDbvh8.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/qS92oIZtCKj1ab2uoPB6fm5AWt1VzSjhHu8MHse1gq0.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/qehskb4sC2FPUhJlhZVDIWEFGyIJrfHJy-CfmphdFns.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/sZS0qKF_2iAHdwVD393APebXubqHUsUtE69Q7r8f1yE.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/ss9-Jy6X2CYapTa3-AmaqJHooTl__r4L-2AlSA7r064.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/t6hRcxh4_1vIzOkNR8o3EdeaZVGSiAyoN3kQuaCo7SQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/xGvF1Ontkjr6KFr90zUF-XMlQOapQmFbUn6Tx88mA6Q.cache +3 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/yD6dVn7E7d6dwJq8Vpkc8T_UEsSCKDHk-T7tZC5o0tk.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/yEGgprrlwc4ukQ7E6vpuEu3-kOSQjKiXj-DsOzQSNXc.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/yLOoNONzDnmCO_K_ZKrI0FRRjxXxITJLlEZNch9_PWs.cache +2 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/yS5gM0yLsgOKvJPwitPGmumYfB2zzWlEqZor91CJQbE.cache +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/yaK012jvbbVi8IYuzZg5oTLpFef3Nh7cVnw57TIbeXk.cache +1 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/v3.0/zMFlf0XznowhcZypOSUD8pcejjdcSdiJ8OVbh0TsTiE.cache +2 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +20 -0
- metadata +463 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 40b620ca2093c8981a36cef260acdfbee3b40b02
|
|
4
|
+
data.tar.gz: 3d7e0355a38d34dc8849122b7abe827781d3adb5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8c0b232a90f377c2b832e47a2ada6c893debd0963b754350c5ccf6b2a0f5df4416e1cece8b029952f16a795080c541d2fa501028aa57f08117c4d7296b4dfab1
|
|
7
|
+
data.tar.gz: 76e3708ae6fe264d1e4172dacee1826820e3161b00cdd20ace53b52663dcc7c78fcb2ad1e2a4bf86ec3bfc2bf3398e0c6bed94a3ae153d61cd4f9c0f0702e5d1
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2015 choonkeat
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# ActiveWaiter
|
|
2
|
+
|
|
3
|
+
A simple mechanism allowing your users to wait for the completion of your `ActiveJob`
|
|
4
|
+
|
|
5
|
+
## Scenario
|
|
6
|
+
|
|
7
|
+
You have an export PDF feature that you've implemented directly in the controller action.
|
|
8
|
+
|
|
9
|
+
As data grows, your HTTP request takes longer and starts timing out. So you decide to move the PDF generating code into a background job.
|
|
10
|
+
|
|
11
|
+
``` ruby
|
|
12
|
+
def index
|
|
13
|
+
respond_to do |format|
|
|
14
|
+
format.html
|
|
15
|
+
format.pdf {
|
|
16
|
+
ExportPdfJob.perform_later(@things, current_user)
|
|
17
|
+
redirect_to :back, notice: "We'll email your PDF when it's done!"
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
But how do you get that PDF into the hands of your users now? Email? Push notification? Manual reload?
|
|
25
|
+
|
|
26
|
+
> You have no PDF ready for download (yet). Please reload.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Solution
|
|
30
|
+
|
|
31
|
+
Let `ActiveWaiter` enqueue that job instead and redirect to it's progress tracking page.
|
|
32
|
+
|
|
33
|
+
``` ruby
|
|
34
|
+
def index
|
|
35
|
+
respond_to do |format|
|
|
36
|
+
format.html
|
|
37
|
+
format.pdf {
|
|
38
|
+
# yay ActiveWaiter.enqueue
|
|
39
|
+
redirect_to active_waiter_path(ActiveWaiter.enqueue(ExportPdfJob, @things, current_user))
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
``` ruby
|
|
46
|
+
# routes.rb
|
|
47
|
+
mount ActiveWaiter::Engine => "/active_waiter(/:id)"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
And we need to add a bit of code into your `ActiveJob` class
|
|
53
|
+
|
|
54
|
+
- 1) add `include ActiveWaiter::Job`
|
|
55
|
+
- 2) return a `url` from your `perform` method to link to the result page (or file)
|
|
56
|
+
|
|
57
|
+
``` ruby
|
|
58
|
+
class ExportPdfJob < ActiveJob::Base
|
|
59
|
+
queue_as :default
|
|
60
|
+
|
|
61
|
+
# (1)
|
|
62
|
+
include ActiveWaiter::Job
|
|
63
|
+
|
|
64
|
+
def perform(things, current_user)
|
|
65
|
+
count = things.count.to_f
|
|
66
|
+
files = []
|
|
67
|
+
things.each_with_index do |thing, index|
|
|
68
|
+
files << generate_pdf(thing)
|
|
69
|
+
|
|
70
|
+
# (a)
|
|
71
|
+
update_active_waiter percentage: (100 * (index+1) / count)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# (2)
|
|
75
|
+
upload(combine(files)).s3_url
|
|
76
|
+
rescue Exception => e
|
|
77
|
+
|
|
78
|
+
# (b)
|
|
79
|
+
update_active_waiter error: e.to_s
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# (c)
|
|
83
|
+
def self.download?
|
|
84
|
+
true
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Optionally, you can also
|
|
90
|
+
|
|
91
|
+
- a) report progress while your job runs, using `update_active_waiter(percentage:)`
|
|
92
|
+
- b) report if there were any errors, using `update_active_waiter(error:)`
|
|
93
|
+
- c) indicate if you want the user to "download" the url manually or be redirected there automatically (default: redirect)
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// compiled file.
|
|
9
|
+
//
|
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
|
11
|
+
// about supported directives.
|
|
12
|
+
//
|
|
13
|
+
//= require jquery
|
|
14
|
+
//= require jquery_ujs
|
|
15
|
+
//= require turbolinks
|
|
16
|
+
//= require_tree .
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
|
11
|
+
* file per style scope.
|
|
12
|
+
*
|
|
13
|
+
*= require_tree .
|
|
14
|
+
*= require_self
|
|
15
|
+
*/
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require_dependency "active_waiter/application_controller"
|
|
2
|
+
|
|
3
|
+
module ActiveWaiter
|
|
4
|
+
class JobsController < ApplicationController
|
|
5
|
+
def show
|
|
6
|
+
data = ActiveWaiter.read(params[:id])
|
|
7
|
+
return on_not_found(data) unless data.respond_to?(:[])
|
|
8
|
+
return on_error(data) if data[:error]
|
|
9
|
+
return on_redirect(data) if data[:redirect_to]
|
|
10
|
+
return on_link_to(data) if data[:link_to]
|
|
11
|
+
return on_progress(data) if data[:percentage]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
protected
|
|
15
|
+
|
|
16
|
+
def on_not_found(data)
|
|
17
|
+
raise ActionController::RoutingError.new('Not Found')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def on_error(data)
|
|
21
|
+
render template: "active_waiter/jobs/error", status: :internal_server_error, locals: data
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def on_redirect(data)
|
|
25
|
+
redirect_to data[:redirect_to]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def on_link_to(data)
|
|
29
|
+
render template: "active_waiter/jobs/link_to", locals: data
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def on_progress(data)
|
|
33
|
+
render template: "active_waiter/jobs/progress", locals: data
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<div class="progress">
|
|
2
|
+
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style="width: 80%; min-width: 3em;">
|
|
3
|
+
<span class="glyphicon glyphicon-exclamation-sign"></span>
|
|
4
|
+
<span><%= error %></span>
|
|
5
|
+
</div>
|
|
6
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<div class="progress">
|
|
2
|
+
<div class="progress-bar progress-bar-success active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%; min-width: 3em;">
|
|
3
|
+
<span>100% Complete</span>
|
|
4
|
+
</div>
|
|
5
|
+
</div>
|
|
6
|
+
<p class="text-right">
|
|
7
|
+
<a href="<%= link_to %>" class="btn btn-primary">
|
|
8
|
+
Click to
|
|
9
|
+
Download
|
|
10
|
+
<span class="glyphicon glyphicon-download"></span>
|
|
11
|
+
</a>
|
|
12
|
+
<p>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<div class="progress">
|
|
2
|
+
<div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="<%= percentage %>" aria-valuemin="0" aria-valuemax="100" style="width: <%= percentage %>%; min-width: 3em;">
|
|
3
|
+
<span><%= number_to_percentage(percentage, precision: 1, strip_insignificant_zeros: true) %> Complete</span>
|
|
4
|
+
</div>
|
|
5
|
+
</div>
|
|
6
|
+
<%= render partial: 'reload' %>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<div class="progress">
|
|
2
|
+
<div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" style="width: 50%; min-width: 3em;">
|
|
3
|
+
<span>Please wait…</span>
|
|
4
|
+
</div>
|
|
5
|
+
</div>
|
|
6
|
+
<%= render partial: 'reload' %>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>ActiveWaiter</title>
|
|
5
|
+
<%= stylesheet_link_tag "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css", media: "all" %>
|
|
6
|
+
<%= stylesheet_link_tag "active_waiter/application", media: "all" %>
|
|
7
|
+
<%= javascript_include_tag "active_waiter/application" %>
|
|
8
|
+
<%= csrf_meta_tags %>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="content">
|
|
12
|
+
<div class="container">
|
|
13
|
+
<div class="row">
|
|
14
|
+
<div class="col-sm-6 col-sm-offset-3">
|
|
15
|
+
<div class="header">
|
|
16
|
+
<h2/>
|
|
17
|
+
</div>
|
|
18
|
+
<%= yield %>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require "active_waiter/engine"
|
|
2
|
+
require "active_waiter/job"
|
|
3
|
+
|
|
4
|
+
module ActiveWaiter
|
|
5
|
+
class << self
|
|
6
|
+
def next_uuid
|
|
7
|
+
SecureRandom.uuid
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def enqueue(klass, *arguments)
|
|
11
|
+
next_uuid.tap do |uid|
|
|
12
|
+
ActiveWaiter.write(uid, {})
|
|
13
|
+
klass.perform_later({ uid: uid }, *arguments)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def write(uid, value)
|
|
18
|
+
Rails.cache.write("active_waiter:#{uid}", value)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def read(uid)
|
|
22
|
+
Rails.cache.read("active_waiter:#{uid}")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module ActiveWaiter::Job
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
included do
|
|
5
|
+
around_perform do |job, block|
|
|
6
|
+
@active_waiter_options = job.arguments.shift
|
|
7
|
+
begin
|
|
8
|
+
key = (self.class.try(:download?) ? :link_to : :redirect_to)
|
|
9
|
+
::ActiveWaiter.write(@active_waiter_options[:uid], {
|
|
10
|
+
percentage: 100,
|
|
11
|
+
key => block.call,
|
|
12
|
+
})
|
|
13
|
+
rescue Exception
|
|
14
|
+
::ActiveWaiter.write(@active_waiter_options[:uid], {
|
|
15
|
+
error: $!.to_s,
|
|
16
|
+
})
|
|
17
|
+
raise
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def update_active_waiter(percentage: nil, error: nil)
|
|
23
|
+
::ActiveWaiter.write(@active_waiter_options[:uid], {
|
|
24
|
+
percentage: percentage && [percentage, 99].min,
|
|
25
|
+
error: error,
|
|
26
|
+
})
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class DummyJob < ActiveJob::Base
|
|
4
|
+
include ActiveWaiter::Job
|
|
5
|
+
|
|
6
|
+
def perform(one, two, three: 3, four: [1,2,3,4])
|
|
7
|
+
[one, two, three, four].to_json
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class ActiveWaiter::JobTest < Minitest::Test
|
|
12
|
+
include ActiveJob::TestHelper
|
|
13
|
+
|
|
14
|
+
def teardown
|
|
15
|
+
clear_enqueued_jobs
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_normal
|
|
19
|
+
assert_equal expected_return_value, DummyJob.new.perform(*arguments)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_active_waiter_enqueue
|
|
23
|
+
ActiveWaiter.stub :next_uuid, uid = "hello" do
|
|
24
|
+
perform_enqueued_jobs do
|
|
25
|
+
assert_equal uid, ActiveWaiter.enqueue(DummyJob, *arguments)
|
|
26
|
+
assert_equal Hash(percentage: 100, redirect_to: expected_return_value), ActiveWaiter.read(uid)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def arguments
|
|
34
|
+
['a', 'b', four: ['a', 'b', 'c']]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def expected_return_value
|
|
38
|
+
['a', 'b', 3, ['a', 'b', 'c']].to_json
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'minitest/mock'
|
|
3
|
+
|
|
4
|
+
class RedirectJob < ActiveJob::Base
|
|
5
|
+
include ActiveWaiter::Job
|
|
6
|
+
|
|
7
|
+
def perform
|
|
8
|
+
"http://other.com/12345"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class DownloadJob < RedirectJob
|
|
13
|
+
def self.download?
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class ActiveWaiter::JobsControllerTest < ActionDispatch::IntegrationTest
|
|
19
|
+
include ActiveJob::TestHelper
|
|
20
|
+
|
|
21
|
+
def setup
|
|
22
|
+
@routes = ActiveWaiter::Engine.routes
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def teardown
|
|
26
|
+
clear_enqueued_jobs
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_show_non_existent
|
|
30
|
+
assert_raises ActionController::RoutingError do
|
|
31
|
+
get '/active_waiter', id: "nosuchjob"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_show_started
|
|
36
|
+
ActiveWaiter.stub :next_uuid, uid do
|
|
37
|
+
assert_equal uid, ActiveWaiter.enqueue(DownloadJob)
|
|
38
|
+
get '/active_waiter', id: uid
|
|
39
|
+
assert_equal 200, status
|
|
40
|
+
assert_match "Please wait", document_root_element.to_s
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_show_error
|
|
45
|
+
ActiveWaiter.write(uid, error: "oops")
|
|
46
|
+
get '/active_waiter', id: uid
|
|
47
|
+
assert_equal 500, status
|
|
48
|
+
assert_match "oops", document_root_element.to_s
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_show_progress
|
|
52
|
+
ActiveWaiter.write(uid, percentage: 42)
|
|
53
|
+
get '/active_waiter', id: uid
|
|
54
|
+
assert_equal 200, status
|
|
55
|
+
assert_match "42%", document_root_element.to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def test_show_completed
|
|
59
|
+
ActiveWaiter.stub :next_uuid, uid do
|
|
60
|
+
perform_enqueued_jobs do
|
|
61
|
+
assert_equal uid, ActiveWaiter.enqueue(DownloadJob)
|
|
62
|
+
get '/active_waiter', id: uid
|
|
63
|
+
assert_equal 200, status
|
|
64
|
+
link = document_root_element.css("a[href='http://other.com/12345']").first
|
|
65
|
+
assert link, "missing hyperlink to returned value"
|
|
66
|
+
assert_match "Click", link.text
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_show_completed_redirect
|
|
72
|
+
ActiveWaiter.stub :next_uuid, uid do
|
|
73
|
+
perform_enqueued_jobs do
|
|
74
|
+
assert_equal uid, ActiveWaiter.enqueue(RedirectJob)
|
|
75
|
+
get '/active_waiter', id: uid
|
|
76
|
+
assert_equal 302, status
|
|
77
|
+
assert_equal "http://other.com/12345", response.location
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def uid
|
|
85
|
+
"hello"
|
|
86
|
+
end
|
|
87
|
+
end
|