active_waiter 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![active_waiter mov](https://cloud.githubusercontent.com/assets/473/7785141/c4667734-01b4-11e5-8974-3a3b00b3a4b6.gif)
|
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
|