workarea 3.4.12

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.
Files changed (571) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +326 -0
  3. data/CHANGELOG.md +20501 -0
  4. data/README.md +163 -0
  5. data/docker-compose.yml +27 -0
  6. data/docs/Gemfile +8 -0
  7. data/docs/bin/middleman +29 -0
  8. data/docs/config.rb +87 -0
  9. data/docs/config.ru +7 -0
  10. data/docs/data/articles.yml +157 -0
  11. data/docs/package.json +15 -0
  12. data/docs/source/404.html.erb +13 -0
  13. data/docs/source/articles/access-routes-in-javascript.html.md +33 -0
  14. data/docs/source/articles/add-a-content-area.html.md +169 -0
  15. data/docs/source/articles/add-a-content-block-type.html.md +334 -0
  16. data/docs/source/articles/add-a-report.html.md +202 -0
  17. data/docs/source/articles/add-css-through-the-admin-ui.html.md +30 -0
  18. data/docs/source/articles/add-javascript-through-a-manifest.html.md +367 -0
  19. data/docs/source/articles/add-javascript-through-a-view.html.md +80 -0
  20. data/docs/source/articles/add-javascript-through-the-admin-ui.html.md +30 -0
  21. data/docs/source/articles/add-metrics.html.md +58 -0
  22. data/docs/source/articles/add-or-replace-a-pricing-calculator.html.md +150 -0
  23. data/docs/source/articles/add-remove-or-change-a-mongoid-validation.html.md +147 -0
  24. data/docs/source/articles/add-remove-or-change-a-product-template.html.md +142 -0
  25. data/docs/source/articles/add-remove-sort-and-group-storefront-search-filters.html.md +483 -0
  26. data/docs/source/articles/add-stylesheets-through-a-manifest.html.md +276 -0
  27. data/docs/source/articles/add-system-content.html.md +138 -0
  28. data/docs/source/articles/analytics-overview.html.md +51 -0
  29. data/docs/source/articles/analyze-storefront-search-results.html.md +261 -0
  30. data/docs/source/articles/api-overview.html.md +35 -0
  31. data/docs/source/articles/appending.html.md +506 -0
  32. data/docs/source/articles/application-document.html.md +88 -0
  33. data/docs/source/articles/automated-javascript-testing.html.md +162 -0
  34. data/docs/source/articles/b2b-overview.html.md +64 -0
  35. data/docs/source/articles/browser-and-device-support.html.md +47 -0
  36. data/docs/source/articles/change-product-placeholder-image.html.md +39 -0
  37. data/docs/source/articles/change-storefront-search-results.html.md +283 -0
  38. data/docs/source/articles/change-the-storefront-product-pricing-ui.html.md +348 -0
  39. data/docs/source/articles/change-the-storefront-search-filters-ui.html.md +103 -0
  40. data/docs/source/articles/checkout.html.md +479 -0
  41. data/docs/source/articles/commerce-model.html.md +164 -0
  42. data/docs/source/articles/configuration-for-hosting.html.md +106 -0
  43. data/docs/source/articles/configuration.html.md +406 -0
  44. data/docs/source/articles/configure-a-payment-gateway.html.md +58 -0
  45. data/docs/source/articles/configure-asset-storage.html.md +29 -0
  46. data/docs/source/articles/configure-asset-types.html.md +18 -0
  47. data/docs/source/articles/configure-contact-form-subjects-list.html.md +24 -0
  48. data/docs/source/articles/configure-imageoptim.html.md +23 -0
  49. data/docs/source/articles/configure-locales.html.md +45 -0
  50. data/docs/source/articles/configure-logins-and-authentication.html.md +42 -0
  51. data/docs/source/articles/configure-low-inventory-threshold.html.md +26 -0
  52. data/docs/source/articles/configure-product-image-sizes-and-processing.html.md +28 -0
  53. data/docs/source/articles/content.html.md +554 -0
  54. data/docs/source/articles/contentable.html.md +41 -0
  55. data/docs/source/articles/contribute-code.html.md +69 -0
  56. data/docs/source/articles/contribute-documentation.html.md +60 -0
  57. data/docs/source/articles/create-a-custom-discount.html.md +234 -0
  58. data/docs/source/articles/create-a-new-app.html.md +131 -0
  59. data/docs/source/articles/create-a-plugin.html.md +19 -0
  60. data/docs/source/articles/create-a-style-guide.html.md +71 -0
  61. data/docs/source/articles/create-a-theme.html.md +134 -0
  62. data/docs/source/articles/css-architectural-overview.html.md +89 -0
  63. data/docs/source/articles/customize-a-helper.html.md +91 -0
  64. data/docs/source/articles/decoration.html.md +415 -0
  65. data/docs/source/articles/define-and-configure-inventory-policies.html.md +107 -0
  66. data/docs/source/articles/documentation-style-guide.html.md +48 -0
  67. data/docs/source/articles/documentation.html.md +54 -0
  68. data/docs/source/articles/domain-modeling.html.md +82 -0
  69. data/docs/source/articles/error-pages.html.md.erb +95 -0
  70. data/docs/source/articles/extension-overview.html.md +152 -0
  71. data/docs/source/articles/favicon-support.html.md +112 -0
  72. data/docs/source/articles/feature-spec-helper-stylesheet.html.md +25 -0
  73. data/docs/source/articles/featurejs-and-feature-spec-helper.html.md +20 -0
  74. data/docs/source/articles/help-and-support.html.md +34 -0
  75. data/docs/source/articles/html-fragment-caching.html.md +46 -0
  76. data/docs/source/articles/http-caching.html.md +43 -0
  77. data/docs/source/articles/i18n.html.md +35 -0
  78. data/docs/source/articles/images-flow.html.md +10 -0
  79. data/docs/source/articles/index-storefront-search-documents.html.md +104 -0
  80. data/docs/source/articles/infrastructure.html.md +46 -0
  81. data/docs/source/articles/installing.html.md +61 -0
  82. data/docs/source/articles/integrate-a-payment-gateway.html.md +124 -0
  83. data/docs/source/articles/integrate-a-web-analytics-provider.html.md +35 -0
  84. data/docs/source/articles/integrate-an-inventory-management-system.html.md +88 -0
  85. data/docs/source/articles/integrating-with-other-software.html.md +59 -0
  86. data/docs/source/articles/inventory.html.md +352 -0
  87. data/docs/source/articles/javascript-coding-standards.html.md +30 -0
  88. data/docs/source/articles/javascript-modules.html.md +174 -0
  89. data/docs/source/articles/javascript-overview.html.md +62 -0
  90. data/docs/source/articles/javascript-reference-documentation.html.md +51 -0
  91. data/docs/source/articles/javascript-templates.html.md +52 -0
  92. data/docs/source/articles/low-level-caching.html.md +25 -0
  93. data/docs/source/articles/maintain-a-plugin.html.md +12 -0
  94. data/docs/source/articles/maintenance-policy.html.md +79 -0
  95. data/docs/source/articles/navigable.html.md +51 -0
  96. data/docs/source/articles/navigating-the-code.html.md +149 -0
  97. data/docs/source/articles/navigation.html.md +386 -0
  98. data/docs/source/articles/order-life-cycle.html.md +546 -0
  99. data/docs/source/articles/order-pricing.html.md +389 -0
  100. data/docs/source/articles/orders-and-items.html.md +210 -0
  101. data/docs/source/articles/orders.html.md +66 -0
  102. data/docs/source/articles/overriding.html.md +155 -0
  103. data/docs/source/articles/overview.html.md +43 -0
  104. data/docs/source/articles/plugins-overview.html.md +12 -0
  105. data/docs/source/articles/prerequisites-and-dependencies.html.md +202 -0
  106. data/docs/source/articles/products.html.md.erb +1270 -0
  107. data/docs/source/articles/progressive-web-application-support.html.md +148 -0
  108. data/docs/source/articles/rails-asset-manifests.html.md +33 -0
  109. data/docs/source/articles/rails-asset-view-helpers.html.md +25 -0
  110. data/docs/source/articles/reading-data.html.md +10 -0
  111. data/docs/source/articles/releasable.html.md +37 -0
  112. data/docs/source/articles/report-a-bug.html.md +75 -0
  113. data/docs/source/articles/ruby-coding-standards.html.md +10 -0
  114. data/docs/source/articles/run-sidekiq-in-a-local-environment.html.md +40 -0
  115. data/docs/source/articles/searching.html.md +1005 -0
  116. data/docs/source/articles/security-policy.html.md +42 -0
  117. data/docs/source/articles/seeds.html.md +345 -0
  118. data/docs/source/articles/shipping.html.md +756 -0
  119. data/docs/source/articles/sort-and-exclude-product-options.html.md +47 -0
  120. data/docs/source/articles/storefront-search-features.html.md +568 -0
  121. data/docs/source/articles/storefront-searches.html.md +126 -0
  122. data/docs/source/articles/style-guides.html.md +21 -0
  123. data/docs/source/articles/stylesheet-coding-standards.html.md +24 -0
  124. data/docs/source/articles/stylesheets-overview.html.md +67 -0
  125. data/docs/source/articles/swappable-list-data-structure.html.md +81 -0
  126. data/docs/source/articles/system-emails.html.md +102 -0
  127. data/docs/source/articles/taggable.html.md +8 -0
  128. data/docs/source/articles/test-a-credit-card-transaction.html.md +16 -0
  129. data/docs/source/articles/test-if-a-plugin-is-installed.html.md +34 -0
  130. data/docs/source/articles/testing.html.md +914 -0
  131. data/docs/source/articles/themes-overview.html.md +155 -0
  132. data/docs/source/articles/translate-administrable-content.html.md +14 -0
  133. data/docs/source/articles/translate-javascript-content.html.md +16 -0
  134. data/docs/source/articles/translate-or-customize-message-content.html.md +29 -0
  135. data/docs/source/articles/translate-or-customize-static-content.html.md +30 -0
  136. data/docs/source/articles/use-an-existing-workarea-app.html.md +108 -0
  137. data/docs/source/articles/view-models.html.md +509 -0
  138. data/docs/source/articles/views.html.md +14 -0
  139. data/docs/source/articles/workers.html.md +613 -0
  140. data/docs/source/articles/writing-data.html.md +10 -0
  141. data/docs/source/cli.html.md +163 -0
  142. data/docs/source/favicon.ico +0 -0
  143. data/docs/source/images/3-variants-1-option.png +0 -0
  144. data/docs/source/images/3-variants-3-options.png +0 -0
  145. data/docs/source/images/3-years-primary-image.png +0 -0
  146. data/docs/source/images/404-storefront-error-page.png +0 -0
  147. data/docs/source/images/404-system-content-admin.png +0 -0
  148. data/docs/source/images/404.jpg +0 -0
  149. data/docs/source/images/5-years-primary-image.png +0 -0
  150. data/docs/source/images/activity-dashboard.png +0 -0
  151. data/docs/source/images/activity-for-object.png +0 -0
  152. data/docs/source/images/activity-ui.png +0 -0
  153. data/docs/source/images/adding-captioned-image-block-custom-icon.png +0 -0
  154. data/docs/source/images/adding-captioned-image-block-default-icon.png +0 -0
  155. data/docs/source/images/admin-alerts-ui.png +0 -0
  156. data/docs/source/images/admin-category-range-filters.png +0 -0
  157. data/docs/source/images/admin-for-3-column-hero.png +0 -0
  158. data/docs/source/images/admin-help-index.png +0 -0
  159. data/docs/source/images/admin-help-ui.png +0 -0
  160. data/docs/source/images/admin-javascript.png +0 -0
  161. data/docs/source/images/admin-notification-for-deactivated-discount.png +0 -0
  162. data/docs/source/images/admin-notifications-ui.png +0 -0
  163. data/docs/source/images/admin-product-show-page.png +0 -0
  164. data/docs/source/images/admin-products-index-page.png +0 -0
  165. data/docs/source/images/admin-range-filters.png +0 -0
  166. data/docs/source/images/admin-style-guides-navigation.png +0 -0
  167. data/docs/source/images/after-re-seeding.png +0 -0
  168. data/docs/source/images/after-seeding-localhost-3000.png +0 -0
  169. data/docs/source/images/after-seeding.png +0 -0
  170. data/docs/source/images/arrow.svg +1 -0
  171. data/docs/source/images/arrow_white.svg +1 -0
  172. data/docs/source/images/aws-resource-map.png +0 -0
  173. data/docs/source/images/backordered-until-output-on-inventory-sku-card.png +0 -0
  174. data/docs/source/images/before-seeding-localhost-3000.png +0 -0
  175. data/docs/source/images/before-seeding.png +0 -0
  176. data/docs/source/images/browsing-workarea-versions-on-the-web.png +0 -0
  177. data/docs/source/images/bulk-asset-upload-on-assets-index-page.png +0 -0
  178. data/docs/source/images/bulk-asset-upload-while-editing-content.png +0 -0
  179. data/docs/source/images/bundle-show-workarea-core.png +0 -0
  180. data/docs/source/images/bundle-show-workarea.png +0 -0
  181. data/docs/source/images/calendar-for-backordered-until-field.png +0 -0
  182. data/docs/source/images/captioned-image-block-in-storefront.png +0 -0
  183. data/docs/source/images/captioned-image-content-block-storefront-component-style-guide.png +0 -0
  184. data/docs/source/images/cart-system-content-in-admin.png +0 -0
  185. data/docs/source/images/cart-system-content-in-storefront.png +0 -0
  186. data/docs/source/images/checkout-addresses-guest.png +0 -0
  187. data/docs/source/images/checkout-addresses-user.png +0 -0
  188. data/docs/source/images/checkout-confirmation.png +0 -0
  189. data/docs/source/images/checkout-flow-0.png +0 -0
  190. data/docs/source/images/checkout-flow-1.png +0 -0
  191. data/docs/source/images/checkout-flow-2.png +0 -0
  192. data/docs/source/images/checkout-flow-3.png +0 -0
  193. data/docs/source/images/checkout-flow-4.png +0 -0
  194. data/docs/source/images/checkout-payment-guest.png +0 -0
  195. data/docs/source/images/checkout-payment-user.png +0 -0
  196. data/docs/source/images/checkout-shipping.png +0 -0
  197. data/docs/source/images/color-picker-component-admin-style-guide.png +0 -0
  198. data/docs/source/images/color-picker-component-on-content-editing-screen.png +0 -0
  199. data/docs/source/images/commerce-model-carts-orders.png +0 -0
  200. data/docs/source/images/commerce-model-order-pricing.png +0 -0
  201. data/docs/source/images/commerce-model.png +0 -0
  202. data/docs/source/images/configuring-an-index-pattern-in-kibana.png +0 -0
  203. data/docs/source/images/content-block-presets.png +0 -0
  204. data/docs/source/images/content-search-customization.png +0 -0
  205. data/docs/source/images/country-with-region-data-in-address-form.png +0 -0
  206. data/docs/source/images/country-without-region-data-in-address-form.png +0 -0
  207. data/docs/source/images/create-content-block-preset-ui.png +0 -0
  208. data/docs/source/images/credit-card-icons.png +0 -0
  209. data/docs/source/images/css-added-through-admin.png +0 -0
  210. data/docs/source/images/css-admin-ui.png +0 -0
  211. data/docs/source/images/current-configuration-shown-in-admin-settings.png +0 -0
  212. data/docs/source/images/customer-impersonation-in-admin.png +0 -0
  213. data/docs/source/images/customer-impersonation-in-store-front.png +0 -0
  214. data/docs/source/images/date-filter-same-day.png +0 -0
  215. data/docs/source/images/developer-toolbar-in-store-front.png +0 -0
  216. data/docs/source/images/discounts-sorted-by-most-redeemed.png +0 -0
  217. data/docs/source/images/edit-help-article.png +0 -0
  218. data/docs/source/images/editing-content-for-search-customization.png +0 -0
  219. data/docs/source/images/editing-dynamic-captioned-image-block.png +0 -0
  220. data/docs/source/images/editing-product-fields-in-the-admin.png +0 -0
  221. data/docs/source/images/editing-search-system-content.png +0 -0
  222. data/docs/source/images/editing-static-captioned-image-block-custom-icon.png +0 -0
  223. data/docs/source/images/editing-static-captioned-image-block-default-icon.png +0 -0
  224. data/docs/source/images/external.svg +1 -0
  225. data/docs/source/images/favicon_16.png +0 -0
  226. data/docs/source/images/favicon_180.png +0 -0
  227. data/docs/source/images/favicon_32.png +0 -0
  228. data/docs/source/images/filters-all.png +0 -0
  229. data/docs/source/images/filters-control.png +0 -0
  230. data/docs/source/images/filters-custom.png +0 -0
  231. data/docs/source/images/filters-groups.png +0 -0
  232. data/docs/source/images/filters-material.png +0 -0
  233. data/docs/source/images/filters-omitted.png +0 -0
  234. data/docs/source/images/filters-pinned.png +0 -0
  235. data/docs/source/images/filters-range.png +0 -0
  236. data/docs/source/images/filters-sorted.png +0 -0
  237. data/docs/source/images/filters-wrapping-to-second-line-in-admin.png +0 -0
  238. data/docs/source/images/generic-product-template-images-no-options-selected.png +0 -0
  239. data/docs/source/images/generic-product-template-images-options-selected.png +0 -0
  240. data/docs/source/images/generic-template.png +0 -0
  241. data/docs/source/images/hosting.svg +1 -0
  242. data/docs/source/images/image-group-content-block-in-storefront.png +0 -0
  243. data/docs/source/images/images.svg +1 -0
  244. data/docs/source/images/import-export-screenshot.png +0 -0
  245. data/docs/source/images/invalid-display.png +0 -0
  246. data/docs/source/images/itcss.png +0 -0
  247. data/docs/source/images/kibana-dev-tools-console.png +0 -0
  248. data/docs/source/images/layout-content-admin-with-2-areas.png +0 -0
  249. data/docs/source/images/layout-content-admin-with-3-areas.png +0 -0
  250. data/docs/source/images/link-to-search-system-content.png +0 -0
  251. data/docs/source/images/logo.svg +1 -0
  252. data/docs/source/images/menu.svg +2 -0
  253. data/docs/source/images/mongo-replica-set.svg +1 -0
  254. data/docs/source/images/multi-column-hero-blocks.png +0 -0
  255. data/docs/source/images/option-selects-product-template-images-options-selected.png +0 -0
  256. data/docs/source/images/option-selects-template.png +0 -0
  257. data/docs/source/images/option-thumbnails-template.png +0 -0
  258. data/docs/source/images/order-item-total-price-diagram.png +0 -0
  259. data/docs/source/images/order-pricing-cart-example.png +0 -0
  260. data/docs/source/images/order-pricing-example-adjustments.png +0 -0
  261. data/docs/source/images/order-pricing-example-totals.png +0 -0
  262. data/docs/source/images/order-pricing-placed-order-example.png +0 -0
  263. data/docs/source/images/order-shipping-total-diagram.png +0 -0
  264. data/docs/source/images/order-show-with-multiple-tenders.png +0 -0
  265. data/docs/source/images/order-subtotal-price-diagram.png +0 -0
  266. data/docs/source/images/order-tax-total-diagram.png +0 -0
  267. data/docs/source/images/order-total-price-diagram.png +0 -0
  268. data/docs/source/images/order-total-value-diagram.png +0 -0
  269. data/docs/source/images/orders-dashboard-links.png +0 -0
  270. data/docs/source/images/oval.svg +1 -0
  271. data/docs/source/images/payment-icon-storefront-style-guide.png +0 -0
  272. data/docs/source/images/people-dashboard-links.png +0 -0
  273. data/docs/source/images/price-adjustments-diagram.png +0 -0
  274. data/docs/source/images/price-display-no-options.png +0 -0
  275. data/docs/source/images/price-display-options-selected.png +0 -0
  276. data/docs/source/images/pricing-calculators-diagram.png +0 -0
  277. data/docs/source/images/product-list-content-block-admin.png +0 -0
  278. data/docs/source/images/product-list-content-block-in-store-front.png +0 -0
  279. data/docs/source/images/promo-products-excluded-autocomplete-results-after.png +0 -0
  280. data/docs/source/images/promo-products-excluded-featured-category-results-after.png +0 -0
  281. data/docs/source/images/promo-products-excluded-recommendations-results-after.png +0 -0
  282. data/docs/source/images/promo-products-excluded-search-category-results-after.png +0 -0
  283. data/docs/source/images/promo-products-excluded-search-results-after.png +0 -0
  284. data/docs/source/images/promo-products-included-autocomplete-results-before.png +0 -0
  285. data/docs/source/images/promo-products-included-featured-category-results-before.png +0 -0
  286. data/docs/source/images/promo-products-included-recommendations-results-before.png +0 -0
  287. data/docs/source/images/promo-products-included-search-category-results-before.png +0 -0
  288. data/docs/source/images/promo-products-included-search-results-before.png +0 -0
  289. data/docs/source/images/rails-version-constraint.png +0 -0
  290. data/docs/source/images/re-enable-discount.png +0 -0
  291. data/docs/source/images/reading-data.svg +1 -0
  292. data/docs/source/images/readme-hero.png +0 -0
  293. data/docs/source/images/redesigned-customized-sort-for-search-results.png +0 -0
  294. data/docs/source/images/reviews-summary-above-share-buttons.png +0 -0
  295. data/docs/source/images/reviews-summary-below-product-name.png +0 -0
  296. data/docs/source/images/reviews-summary-below-share-buttons.png +0 -0
  297. data/docs/source/images/reviews-summary-removed.png +0 -0
  298. data/docs/source/images/rsa-fingerprint-for-stash.png +0 -0
  299. data/docs/source/images/ruby-version-constraint.png +0 -0
  300. data/docs/source/images/script-tag-added-through-admin.png +0 -0
  301. data/docs/source/images/search-analysis-admin-alternate-rendering.png +0 -0
  302. data/docs/source/images/search-analysis-admin.png +0 -0
  303. data/docs/source/images/search-quality-report.png +0 -0
  304. data/docs/source/images/search.svg +1 -0
  305. data/docs/source/images/searching-for-cart-system-content-in-admin.png +0 -0
  306. data/docs/source/images/searching-for-layout-system-content-in-admin.png +0 -0
  307. data/docs/source/images/seeded-admin.png +0 -0
  308. data/docs/source/images/seeds-from-plugins.png +0 -0
  309. data/docs/source/images/seo-metadata-automation-ui.png +0 -0
  310. data/docs/source/images/show-password-button.png +0 -0
  311. data/docs/source/images/storefront-autocomplete.png +0 -0
  312. data/docs/source/images/storefront-category-summary-content-block.png +0 -0
  313. data/docs/source/images/storefront-category.png +0 -0
  314. data/docs/source/images/storefront-product-after-overriding.png +0 -0
  315. data/docs/source/images/storefront-product-before-overriding.png +0 -0
  316. data/docs/source/images/storefront-product-browse-page.png +0 -0
  317. data/docs/source/images/storefront-product-recommendations.png +0 -0
  318. data/docs/source/images/storefront-product-show-page.png +0 -0
  319. data/docs/source/images/storefront-requests-and-search-requests.png +0 -0
  320. data/docs/source/images/storefront-search-request-handling.png +0 -0
  321. data/docs/source/images/storefront-search-response-creation.png +0 -0
  322. data/docs/source/images/storefront-search.png +0 -0
  323. data/docs/source/images/storefront-style-guides-navigation.png +0 -0
  324. data/docs/source/images/styles.css +3 -0
  325. data/docs/source/images/tax-categories-ui.png +0 -0
  326. data/docs/source/images/tax-rates-ui.png +0 -0
  327. data/docs/source/images/unpurchasable-product.png +0 -0
  328. data/docs/source/images/url-redirects-filtering.png +0 -0
  329. data/docs/source/images/utility-nav-area-in-admin.png +0 -0
  330. data/docs/source/images/utility-nav-area-in-storefront.png +0 -0
  331. data/docs/source/images/validation-message-in-storefront.png +0 -0
  332. data/docs/source/images/view-model-interface.png +0 -0
  333. data/docs/source/images/viewing-workarea-version-in-source.png +0 -0
  334. data/docs/source/images/workarea.svg +1 -0
  335. data/docs/source/images/worst-performing-searches-on-results-customization-page.png +0 -0
  336. data/docs/source/images/writing-data.svg +1 -0
  337. data/docs/source/index.html.erb +167 -0
  338. data/docs/source/javascripts/jquery.js +2 -0
  339. data/docs/source/javascripts/lunr.js +7 -0
  340. data/docs/source/javascripts/site.js +299 -0
  341. data/docs/source/javascripts/vendor/highlight.pack.js +2 -0
  342. data/docs/source/layouts/article.erb +106 -0
  343. data/docs/source/layouts/bare.erb +46 -0
  344. data/docs/source/layouts/layout.erb +43 -0
  345. data/docs/source/release-notes.html.md +258 -0
  346. data/docs/source/release-notes/workarea-3-0-0.html.md +146 -0
  347. data/docs/source/release-notes/workarea-3-0-1.html.md +161 -0
  348. data/docs/source/release-notes/workarea-3-0-10.html.md +39 -0
  349. data/docs/source/release-notes/workarea-3-0-11.html.md +277 -0
  350. data/docs/source/release-notes/workarea-3-0-12.html.md +14 -0
  351. data/docs/source/release-notes/workarea-3-0-13.html.md +153 -0
  352. data/docs/source/release-notes/workarea-3-0-14.html.md +93 -0
  353. data/docs/source/release-notes/workarea-3-0-15.html.md +107 -0
  354. data/docs/source/release-notes/workarea-3-0-16.html.md +36 -0
  355. data/docs/source/release-notes/workarea-3-0-17.html.md +141 -0
  356. data/docs/source/release-notes/workarea-3-0-18.html.md +123 -0
  357. data/docs/source/release-notes/workarea-3-0-19.html.md +160 -0
  358. data/docs/source/release-notes/workarea-3-0-2.html.md +222 -0
  359. data/docs/source/release-notes/workarea-3-0-20.html.md +95 -0
  360. data/docs/source/release-notes/workarea-3-0-21.html.md +168 -0
  361. data/docs/source/release-notes/workarea-3-0-22.html.md +268 -0
  362. data/docs/source/release-notes/workarea-3-0-23.html.md +173 -0
  363. data/docs/source/release-notes/workarea-3-0-24.html.md +19 -0
  364. data/docs/source/release-notes/workarea-3-0-25.html.md +26 -0
  365. data/docs/source/release-notes/workarea-3-0-26.html.md +199 -0
  366. data/docs/source/release-notes/workarea-3-0-27.html.md +113 -0
  367. data/docs/source/release-notes/workarea-3-0-28.html.md +39 -0
  368. data/docs/source/release-notes/workarea-3-0-29.html.md +73 -0
  369. data/docs/source/release-notes/workarea-3-0-3.html.md +35 -0
  370. data/docs/source/release-notes/workarea-3-0-30.html.md +186 -0
  371. data/docs/source/release-notes/workarea-3-0-31.html.md +125 -0
  372. data/docs/source/release-notes/workarea-3-0-32.html.md +73 -0
  373. data/docs/source/release-notes/workarea-3-0-33.html.md +137 -0
  374. data/docs/source/release-notes/workarea-3-0-34.html.md +203 -0
  375. data/docs/source/release-notes/workarea-3-0-35.html.md +205 -0
  376. data/docs/source/release-notes/workarea-3-0-36.html.md +105 -0
  377. data/docs/source/release-notes/workarea-3-0-37.html.md +144 -0
  378. data/docs/source/release-notes/workarea-3-0-38.html.md +73 -0
  379. data/docs/source/release-notes/workarea-3-0-39.html.md +77 -0
  380. data/docs/source/release-notes/workarea-3-0-4.html.md +14 -0
  381. data/docs/source/release-notes/workarea-3-0-40.html.md +130 -0
  382. data/docs/source/release-notes/workarea-3-0-41.html.md +70 -0
  383. data/docs/source/release-notes/workarea-3-0-42.html.md +52 -0
  384. data/docs/source/release-notes/workarea-3-0-43.html.md +72 -0
  385. data/docs/source/release-notes/workarea-3-0-44.html.md +93 -0
  386. data/docs/source/release-notes/workarea-3-0-45.html.md +61 -0
  387. data/docs/source/release-notes/workarea-3-0-46.html.md +171 -0
  388. data/docs/source/release-notes/workarea-3-0-47.html.md +130 -0
  389. data/docs/source/release-notes/workarea-3-0-48.html.md +160 -0
  390. data/docs/source/release-notes/workarea-3-0-49.html.md +28 -0
  391. data/docs/source/release-notes/workarea-3-0-5.html.md +225 -0
  392. data/docs/source/release-notes/workarea-3-0-50.html.md +74 -0
  393. data/docs/source/release-notes/workarea-3-0-51.html.md +61 -0
  394. data/docs/source/release-notes/workarea-3-0-52.html.md +76 -0
  395. data/docs/source/release-notes/workarea-3-0-53.html.md +126 -0
  396. data/docs/source/release-notes/workarea-3-0-54.html.md +112 -0
  397. data/docs/source/release-notes/workarea-3-0-55.html.md +105 -0
  398. data/docs/source/release-notes/workarea-3-0-56.html.md +56 -0
  399. data/docs/source/release-notes/workarea-3-0-57.html.md +82 -0
  400. data/docs/source/release-notes/workarea-3-0-58.html.md +153 -0
  401. data/docs/source/release-notes/workarea-3-0-59.html.md +78 -0
  402. data/docs/source/release-notes/workarea-3-0-6.html.md +165 -0
  403. data/docs/source/release-notes/workarea-3-0-60.html.md +43 -0
  404. data/docs/source/release-notes/workarea-3-0-61.html.md +46 -0
  405. data/docs/source/release-notes/workarea-3-0-62.html.md +23 -0
  406. data/docs/source/release-notes/workarea-3-0-63.html.md +25 -0
  407. data/docs/source/release-notes/workarea-3-0-64.html.md +25 -0
  408. data/docs/source/release-notes/workarea-3-0-65.html.md +37 -0
  409. data/docs/source/release-notes/workarea-3-0-7.html.md +207 -0
  410. data/docs/source/release-notes/workarea-3-0-8.html.md +337 -0
  411. data/docs/source/release-notes/workarea-3-0-9.html.md +196 -0
  412. data/docs/source/release-notes/workarea-3-1-0.html.md +414 -0
  413. data/docs/source/release-notes/workarea-3-1-1.html.md +139 -0
  414. data/docs/source/release-notes/workarea-3-1-10.html.md +19 -0
  415. data/docs/source/release-notes/workarea-3-1-11.html.md +27 -0
  416. data/docs/source/release-notes/workarea-3-1-12.html.md +216 -0
  417. data/docs/source/release-notes/workarea-3-1-13.html.md +113 -0
  418. data/docs/source/release-notes/workarea-3-1-14.html.md +39 -0
  419. data/docs/source/release-notes/workarea-3-1-15.html.md +107 -0
  420. data/docs/source/release-notes/workarea-3-1-16.html.md +188 -0
  421. data/docs/source/release-notes/workarea-3-1-17.html.md +141 -0
  422. data/docs/source/release-notes/workarea-3-1-18.html.md +73 -0
  423. data/docs/source/release-notes/workarea-3-1-19.html.md +137 -0
  424. data/docs/source/release-notes/workarea-3-1-2.html.md +55 -0
  425. data/docs/source/release-notes/workarea-3-1-20.html.md +203 -0
  426. data/docs/source/release-notes/workarea-3-1-21.html.md +205 -0
  427. data/docs/source/release-notes/workarea-3-1-22.html.md +121 -0
  428. data/docs/source/release-notes/workarea-3-1-23.html.md +144 -0
  429. data/docs/source/release-notes/workarea-3-1-24.html.md +94 -0
  430. data/docs/source/release-notes/workarea-3-1-25.html.md +77 -0
  431. data/docs/source/release-notes/workarea-3-1-26.html.md +130 -0
  432. data/docs/source/release-notes/workarea-3-1-27.html.md +70 -0
  433. data/docs/source/release-notes/workarea-3-1-28.html.md +52 -0
  434. data/docs/source/release-notes/workarea-3-1-29.html.md +44 -0
  435. data/docs/source/release-notes/workarea-3-1-3.html.md +185 -0
  436. data/docs/source/release-notes/workarea-3-1-30.html.md +72 -0
  437. data/docs/source/release-notes/workarea-3-1-31.html.md +93 -0
  438. data/docs/source/release-notes/workarea-3-1-32.html.md +61 -0
  439. data/docs/source/release-notes/workarea-3-1-33.html.md +171 -0
  440. data/docs/source/release-notes/workarea-3-1-34.html.md +130 -0
  441. data/docs/source/release-notes/workarea-3-1-35.html.md +179 -0
  442. data/docs/source/release-notes/workarea-3-1-36.html.md +28 -0
  443. data/docs/source/release-notes/workarea-3-1-37.html.md +74 -0
  444. data/docs/source/release-notes/workarea-3-1-38.html.md +61 -0
  445. data/docs/source/release-notes/workarea-3-1-39.html.md +96 -0
  446. data/docs/source/release-notes/workarea-3-1-4.html.md +148 -0
  447. data/docs/source/release-notes/workarea-3-1-40.html.md +126 -0
  448. data/docs/source/release-notes/workarea-3-1-41.html.md +128 -0
  449. data/docs/source/release-notes/workarea-3-1-42.html.md +105 -0
  450. data/docs/source/release-notes/workarea-3-1-43.html.md +37 -0
  451. data/docs/source/release-notes/workarea-3-1-44.html.md +82 -0
  452. data/docs/source/release-notes/workarea-3-1-45.html.md +153 -0
  453. data/docs/source/release-notes/workarea-3-1-46.html.md +91 -0
  454. data/docs/source/release-notes/workarea-3-1-47.html.md +65 -0
  455. data/docs/source/release-notes/workarea-3-1-48.html.md +46 -0
  456. data/docs/source/release-notes/workarea-3-1-49.html.md +23 -0
  457. data/docs/source/release-notes/workarea-3-1-5.html.md +169 -0
  458. data/docs/source/release-notes/workarea-3-1-50.html.md +42 -0
  459. data/docs/source/release-notes/workarea-3-1-51.html.md +25 -0
  460. data/docs/source/release-notes/workarea-3-1-52.html.md +57 -0
  461. data/docs/source/release-notes/workarea-3-1-6.html.md +117 -0
  462. data/docs/source/release-notes/workarea-3-1-7.html.md +176 -0
  463. data/docs/source/release-notes/workarea-3-1-8.html.md +283 -0
  464. data/docs/source/release-notes/workarea-3-1-9.html.md +212 -0
  465. data/docs/source/release-notes/workarea-3-2-0.html.md +1705 -0
  466. data/docs/source/release-notes/workarea-3-2-1.html.md +216 -0
  467. data/docs/source/release-notes/workarea-3-2-10.html.md +237 -0
  468. data/docs/source/release-notes/workarea-3-2-11.html.md +121 -0
  469. data/docs/source/release-notes/workarea-3-2-12.html.md +145 -0
  470. data/docs/source/release-notes/workarea-3-2-13.html.md +138 -0
  471. data/docs/source/release-notes/workarea-3-2-14.html.md +77 -0
  472. data/docs/source/release-notes/workarea-3-2-15.html.md +130 -0
  473. data/docs/source/release-notes/workarea-3-2-16.html.md +111 -0
  474. data/docs/source/release-notes/workarea-3-2-17.html.md +52 -0
  475. data/docs/source/release-notes/workarea-3-2-18.html.md +44 -0
  476. data/docs/source/release-notes/workarea-3-2-19.html.md +72 -0
  477. data/docs/source/release-notes/workarea-3-2-2.html.md +145 -0
  478. data/docs/source/release-notes/workarea-3-2-20.html.md +93 -0
  479. data/docs/source/release-notes/workarea-3-2-21.html.md +61 -0
  480. data/docs/source/release-notes/workarea-3-2-22.html.md +154 -0
  481. data/docs/source/release-notes/workarea-3-2-23.html.md +130 -0
  482. data/docs/source/release-notes/workarea-3-2-24.html.md +200 -0
  483. data/docs/source/release-notes/workarea-3-2-25.html.md +28 -0
  484. data/docs/source/release-notes/workarea-3-2-26.html.md +94 -0
  485. data/docs/source/release-notes/workarea-3-2-27.html.md +61 -0
  486. data/docs/source/release-notes/workarea-3-2-28.html.md +96 -0
  487. data/docs/source/release-notes/workarea-3-2-29.html.md +126 -0
  488. data/docs/source/release-notes/workarea-3-2-30.html.md +112 -0
  489. data/docs/source/release-notes/workarea-3-2-31.html.md +105 -0
  490. data/docs/source/release-notes/workarea-3-2-32.html.md +56 -0
  491. data/docs/source/release-notes/workarea-3-2-33.html.md +82 -0
  492. data/docs/source/release-notes/workarea-3-2-34.html.md +153 -0
  493. data/docs/source/release-notes/workarea-3-2-35.html.md +91 -0
  494. data/docs/source/release-notes/workarea-3-2-36.html.md +118 -0
  495. data/docs/source/release-notes/workarea-3-2-37.html.md +46 -0
  496. data/docs/source/release-notes/workarea-3-2-38.html.md +23 -0
  497. data/docs/source/release-notes/workarea-3-2-39.html.md +42 -0
  498. data/docs/source/release-notes/workarea-3-2-4.html.md +109 -0
  499. data/docs/source/release-notes/workarea-3-2-40.html.md +25 -0
  500. data/docs/source/release-notes/workarea-3-2-41.html.md +90 -0
  501. data/docs/source/release-notes/workarea-3-2-5.html.md +186 -0
  502. data/docs/source/release-notes/workarea-3-2-6.html.md +173 -0
  503. data/docs/source/release-notes/workarea-3-2-7.html.md +89 -0
  504. data/docs/source/release-notes/workarea-3-2-8.html.md +137 -0
  505. data/docs/source/release-notes/workarea-3-2-9.html.md +219 -0
  506. data/docs/source/release-notes/workarea-3-3-0.html.md +1272 -0
  507. data/docs/source/release-notes/workarea-3-3-1.html.md +324 -0
  508. data/docs/source/release-notes/workarea-3-3-10.html.md +69 -0
  509. data/docs/source/release-notes/workarea-3-3-11.html.md +72 -0
  510. data/docs/source/release-notes/workarea-3-3-12.html.md +136 -0
  511. data/docs/source/release-notes/workarea-3-3-13.html.md +61 -0
  512. data/docs/source/release-notes/workarea-3-3-14.html.md +196 -0
  513. data/docs/source/release-notes/workarea-3-3-15.html.md +167 -0
  514. data/docs/source/release-notes/workarea-3-3-16.html.md +234 -0
  515. data/docs/source/release-notes/workarea-3-3-17.html.md +82 -0
  516. data/docs/source/release-notes/workarea-3-3-18.html.md +165 -0
  517. data/docs/source/release-notes/workarea-3-3-19.html.md +106 -0
  518. data/docs/source/release-notes/workarea-3-3-2.html.md +72 -0
  519. data/docs/source/release-notes/workarea-3-3-20.html.md +116 -0
  520. data/docs/source/release-notes/workarea-3-3-21.html.md +228 -0
  521. data/docs/source/release-notes/workarea-3-3-22.html.md +125 -0
  522. data/docs/source/release-notes/workarea-3-3-23.html.md +154 -0
  523. data/docs/source/release-notes/workarea-3-3-24.html.md +70 -0
  524. data/docs/source/release-notes/workarea-3-3-25.html.md +114 -0
  525. data/docs/source/release-notes/workarea-3-3-26.html.md +260 -0
  526. data/docs/source/release-notes/workarea-3-3-27.html.md +138 -0
  527. data/docs/source/release-notes/workarea-3-3-28.html.md +147 -0
  528. data/docs/source/release-notes/workarea-3-3-29.html.md +63 -0
  529. data/docs/source/release-notes/workarea-3-3-3.html.md +153 -0
  530. data/docs/source/release-notes/workarea-3-3-30.html.md +102 -0
  531. data/docs/source/release-notes/workarea-3-3-31.html.md +57 -0
  532. data/docs/source/release-notes/workarea-3-3-32.html.md +44 -0
  533. data/docs/source/release-notes/workarea-3-3-33.html.md +114 -0
  534. data/docs/source/release-notes/workarea-3-3-4.html.md +332 -0
  535. data/docs/source/release-notes/workarea-3-3-5.html.md +242 -0
  536. data/docs/source/release-notes/workarea-3-3-6.html.md +100 -0
  537. data/docs/source/release-notes/workarea-3-3-7.html.md +148 -0
  538. data/docs/source/release-notes/workarea-3-3-8.html.md +163 -0
  539. data/docs/source/release-notes/workarea-3-3-9.html.md +93 -0
  540. data/docs/source/release-notes/workarea-3-4-0.html.md +580 -0
  541. data/docs/source/release-notes/workarea-3-4-1.html.md +150 -0
  542. data/docs/source/release-notes/workarea-3-4-10.html.md +72 -0
  543. data/docs/source/release-notes/workarea-3-4-11.html.md +60 -0
  544. data/docs/source/release-notes/workarea-3-4-12.html.md +155 -0
  545. data/docs/source/release-notes/workarea-3-4-2.html.md +188 -0
  546. data/docs/source/release-notes/workarea-3-4-3.html.md +136 -0
  547. data/docs/source/release-notes/workarea-3-4-4.html.md +114 -0
  548. data/docs/source/release-notes/workarea-3-4-5.html.md +275 -0
  549. data/docs/source/release-notes/workarea-3-4-6.html.md +169 -0
  550. data/docs/source/release-notes/workarea-3-4-7.html.md +162 -0
  551. data/docs/source/release-notes/workarea-3-4-8.html.md +95 -0
  552. data/docs/source/release-notes/workarea-3-4-9.html.md +135 -0
  553. data/docs/source/search.html.erb +34 -0
  554. data/docs/source/shared/_header.erb +61 -0
  555. data/docs/source/shared/_svgs.erb +17 -0
  556. data/docs/source/style_guide/index.html.erb +382 -0
  557. data/docs/source/stylesheets/_base.scss +125 -0
  558. data/docs/source/stylesheets/_components.scss +669 -0
  559. data/docs/source/stylesheets/_helpers.scss +10 -0
  560. data/docs/source/stylesheets/_opinions.scss +42 -0
  561. data/docs/source/stylesheets/_settings.scss +56 -0
  562. data/docs/source/stylesheets/_typography.scss +119 -0
  563. data/docs/source/stylesheets/site.css.scss +14 -0
  564. data/docs/source/stylesheets/vendor/_avalanche.scss +328 -0
  565. data/docs/source/stylesheets/vendor/_normalize.scss +341 -0
  566. data/docs/source/stylesheets/vendor/highlight/_tomorrow_night_blue.scss +75 -0
  567. data/docs/source/upgrade-guides.html.md +18 -0
  568. data/docs/source/upgrade-guides/workarea-3-4-0.html.md +152 -0
  569. data/docs/workarea_renderer.rb +8 -0
  570. data/docs/yarn.lock +2522 -0
  571. metadata +669 -0
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Views
3
+ excerpt: Workarea views are written in Haml, but are otherwise no different from vanilla Rails views.
4
+ ---
5
+
6
+ # Views
7
+
8
+ Workarea views are written in [Haml](http://haml.info/), but are otherwise no different from vanilla Rails views.
9
+
10
+ You do not need to stick with Haml when [overriding views](overriding.html). You may change the file extension and use whichever templating language you prefer and Rails will prefer your view over the same view from Workarea.
11
+
12
+ For HTML naming conventions and idioms used in Workarea, review the [stylesheet coding standards](stylesheet-coding-standards.html).
13
+
14
+
@@ -0,0 +1,613 @@
1
+ ---
2
+ title: Workers
3
+ excerpt: Workarea applications use Sidekiq as a job queuing backend to perform units of work asynchronously in the background. These jobs, which include search indexing, cache busting, and cleanup of expired data, are defined as workers. Workarea workers build
4
+ ---
5
+
6
+ # Workers
7
+
8
+ Workarea applications use [Sidekiq](https://github.com/mperham/sidekiq) as a job queuing backend to perform units of work asynchronously in the background. These jobs, which include search indexing, cache busting, and cleanup of expired data, are defined as <dfn>workers</dfn>. Workarea workers build on Sidekiq's worker concept and are typically enqueued on a schedule or in response to callbacks on [application documents](application-document.html).
9
+
10
+ ## Sidekiq Workers
11
+
12
+ Sidekiq workers are classes that include `Sidekiq::Worker` ([docs](http://www.rubydoc.info/github/mperham/sidekiq/Sidekiq/Worker)) and represent units of work that may be performed immediately (inline) or may be enqueued to be performed in the background (async). A Sidekiq worker must implement the `perform` instance method, whose signature will vary depending on how the worker is intended to be used. The example below is intended to be called with a hash of attributes that will be used to create a model instance.
13
+
14
+ ```ruby
15
+ class CreateCategory
16
+ include Sidekiq::Worker
17
+
18
+ def perform(attributes)
19
+ Workarea::Catalog::Category.create!(attributes)
20
+ end
21
+ end
22
+
23
+ # Run inline
24
+ CreateCategory.new.perform(name: 'Shirts')
25
+
26
+ # Run async (enqueue)
27
+ CreateCategory.perform_async(name: 'Shirts')
28
+ ```
29
+
30
+ ### Inline Sidekiq
31
+
32
+ When `Sidekiq::Testing.inline!` is `true`, the inline and async examples above behave the same. The async example is run synchronously and is not enqueued into Sidekiq.
33
+
34
+ In many cases, a Sidekiq process is not running in a development environment, so Workarea applications include the following configuration which defaults `Sidekiq::Testing.inline!` to `true` in the Development environment.
35
+
36
+ ```ruby
37
+ # your_app/config/environments/development.rb
38
+
39
+ Rails.application.configure do
40
+ # Run Sidekiq tasks synchronously so that Sidekiq is not required in Development
41
+ require 'sidekiq/testing/inline'
42
+
43
+ # ...
44
+ end
45
+ ```
46
+
47
+ ### Worker Options & Queues
48
+
49
+ Within a worker class definition, the `sidekiq_options` method declares [options for that worker](https://github.com/mperham/sidekiq/wiki/Advanced-Options#workers). Sidekiq worker options include `retry`, to set the worker's retry behavior, and `queue`, to enqueue the worker into a specific [queue](https://github.com/mperham/sidekiq/wiki/Advanced-Options#queues).
50
+
51
+ Workarea applications include a [Sidekiq configuration file](https://github.com/mperham/sidekiq/wiki/Advanced-Options#the-sidekiq-configuration-file) that configures Sidekiq to use 4 queues: _high_, _default_, _low_, and _mailers_.
52
+
53
+ ## Workarea Workers
54
+
55
+ Workarea workers are simply Sidekiq workers defined within the `Workarea` namespace. Workers are defined within Workarea engines and applications at the path _app/workers/workarea/worker\_name.rb_.
56
+
57
+ Some Workarea workers are re-used outside the context of Sidekiq and therefore have additional convenience methods. This is particularly true of workers used to index documents into Elasticsearch. The worker shown below includes two public class methods in addition to the conventional `perform` instance method.
58
+
59
+ ```ruby
60
+ module Workarea
61
+ class BulkIndexProducts
62
+ include Sidekiq::Worker
63
+ # ...
64
+
65
+ class << self
66
+ def perform(ids = Catalog::Product.pluck(:id))
67
+ # ...
68
+ end
69
+
70
+ def perform_by_models(products)
71
+ # ...
72
+ end
73
+ end
74
+
75
+ def perform(ids)
76
+ self.class.perform(ids)
77
+ end
78
+ end
79
+ end
80
+ ```
81
+
82
+ `BulkIndexProducts.perform` accepts a collection of product ids, defaulting to **all** product ids if a collection is not provided. The `perform` instance method used by Sidekiq delegates to this method. `BulkIndexProducts.perform_by_models` accepts a collection of product model instances instead of a collection of ids.
83
+
84
+ In the example below, the `perform` class method expects a model instance instead of an id. This is a common pattern among workers that operate on a model instance.
85
+
86
+ ```ruby
87
+ module Workarea
88
+ class IndexAdminSearch
89
+ include Sidekiq::Worker
90
+ include Sidekiq::CallbacksWorker
91
+
92
+ #...
93
+
94
+ def self.perform(model)
95
+ # ...
96
+ end
97
+
98
+ def perform(class_name, id)
99
+ model = class_name.constantize.find_or_initialize_by(id: id)
100
+ self.class.perform(model)
101
+ end
102
+ end
103
+ end
104
+ ```
105
+
106
+ Again, the `perform` instance method uses the `perform` class method within its implementation.
107
+
108
+ These additional APIs are useful for a variety of <abbr title="command-line interface">CLI</abbr> and scripting use cases, such as rake tasks used to re-index Elasticsearch.
109
+
110
+ ## Sidekiq Cron Job
111
+
112
+ Many Workarea workers are used for cleanup and other recurring tasks and are enqueued on a fixed schedule. Within an engine or application, each instance of `Sidekiq::Cron::Job` ([docs](http://www.rubydoc.info/gems/sidekiq-cron/Sidekiq/Cron/Job), also see [Sidekiq-Cron](https://github.com/ondrejbartas/sidekiq-cron)) schedules a worker to be enqueued on a schedule, which is declared using cron notation.
113
+
114
+ Cron jobs are declared within an initializer like the one shown below.
115
+
116
+ ```ruby
117
+ # workarea-core/config/initializers/05_scheduled_jobs.rb
118
+
119
+ Sidekiq::Cron::Job.create(
120
+ name: 'Workarea::AnalyticsWeeklyUpdate',
121
+ klass: 'Workarea::AnalyticsWeeklyUpdate',
122
+ cron: '0 0 * * 0',
123
+ queue: 'high'
124
+ )
125
+
126
+ Sidekiq::Cron::Job.create(
127
+ name: 'Workarea::AnalyticsDailyUpdate',
128
+ klass: 'Workarea::AnalyticsDailyUpdate',
129
+ cron: '0 0 * * *',
130
+ queue: 'high'
131
+ )
132
+
133
+ Sidekiq::Cron::Job.create(
134
+ name: 'Workarea::CleanInventoryTransactions',
135
+ klass: 'Workarea::CleanInventoryTransactions',
136
+ cron: '0 5 * * *',
137
+ queue: 'low'
138
+ )
139
+
140
+ # ...
141
+ ```
142
+
143
+ ### Cron Job Arguments
144
+
145
+ Workers run as cron jobs typically do not make use of arguments, so the `perform` method of these workers usually takes one of the following forms.
146
+
147
+ ```ruby
148
+ # workarea-core/app/workers/workarea/analytics_daily_update.rb
149
+
150
+ module Workarea
151
+ class AnalyticsDailyUpdate
152
+ include Sidekiq::Worker
153
+
154
+ def perform(*)
155
+ Analytics::TimeSeries.reset_for_today!
156
+ end
157
+ end
158
+ end
159
+
160
+ # workarea-core/app/workers/workarea/clean_inventory_transactions.rb
161
+
162
+ module Workarea
163
+ class CleanInventoryTransactions
164
+ include Sidekiq::Worker
165
+
166
+ def perform(*args)
167
+ Inventory::Transaction.expired.delete_all
168
+ end
169
+ end
170
+ end
171
+ ```
172
+
173
+ ## Callbacks Worker
174
+
175
+ Instead of binding to a schedule, many workers are run or enqueued in response to callbacks representing the life cycles of [application documents](application-document.html) or other objects. These workers are referred to as <dfn>callbacks workers</dfn>.
176
+
177
+ Callbacks workers include the module `Sidekiq::CallbacksWorker`, which is a Workarea extension to Sidekiq. Among other things, this module provides the `enqueue_on` Sidekiq worker option, which allows a worker to register itself to be run or enqueued in response to any [ActiveSupport callback](http://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html).
178
+
179
+ ActiveSupport defines <dfn>callbacks</dfn> as "code hooks that are run at key points in an object's life cycle". In practice, callbacks workers are primarily concerned with [Mongoid callbacks](https://docs.mongodb.com/ruby-driver/master/tutorials/6.1.0/mongoid-callbacks/) representing changes to an application document, such as `save` and `destroy`. Some custom callbacks are also important, such as the `place` callback on `Workarea::Order`.
180
+
181
+ ### Declaring Callbacks & Arguments
182
+
183
+ Callbacks workers use the `enqueue_on` option to declare which callbacks on which classes will cause the worker to be run or enqueued. The `with` sub option may be used to declare the arguments that will be passed to `perform` when the worker is run. Furthermore, the `ignore_if` and `only_if` options may be used to conditionally run/enqueue the worker.
184
+
185
+ In the simplest case, a worker declares a single callback on a single class. When run, `perform` receives the `id` of the instance that triggered the callback. The following worker will be run or enqueued after instances of `Navigation::Taxon` are saved.
186
+
187
+ ```ruby
188
+ module Workarea
189
+ class BustNavigationCache
190
+ include Sidekiq::Worker
191
+ include Sidekiq::CallbacksWorker
192
+
193
+ sidekiq_options enqueue_on: { Navigation::Taxon => :save }
194
+
195
+ def perform(id)
196
+ # ...
197
+ end
198
+ end
199
+ end
200
+ ```
201
+
202
+ The following code listing shows examples that declare multiple classes and callbacks.
203
+
204
+ ```ruby
205
+ sidekiq_options enqueue_on: { Pricing::Discount => [:save, :destroy] }
206
+
207
+ sidekiq_options(
208
+ enqueue_on: {
209
+ Inventory::Sku => [:save, :destroy],
210
+ Pricing::Sku => [:save, :destroy]
211
+ }
212
+ )
213
+
214
+ sidekiq_options(
215
+ enqueue_on: {
216
+ Order => [:create, :place, :destroy],
217
+ Fulfillment => [:update]
218
+ }
219
+ )
220
+ ```
221
+
222
+ The following examples provide a value to `with` to declare the arguments to be passed to `perform` when the worker is run. The value of `with` is a lambda that will be evaluated in the context of the object that triggered the callback (using `instance_exec`). Note how the signature of `perform` changes in each example to match the array returned by the `with` lambda.
223
+
224
+ ```ruby
225
+ # passes the release changes in addition to the id
226
+ module Workarea
227
+ class UpdatePaymentProfileEmail
228
+ include Sidekiq::Worker
229
+ include Sidekiq::CallbacksWorker
230
+
231
+ sidekiq_options(
232
+ enqueue_on: {
233
+ User => :update,
234
+ with: -> { [id, changes] }
235
+ }
236
+ )
237
+
238
+ def perform(id, changes)
239
+ # ...
240
+ end
241
+ end
242
+ end
243
+
244
+ # passes the changes only (no id)
245
+ module Workarea
246
+ class IndexCategoryChanges
247
+ include Sidekiq::Worker
248
+ include Sidekiq::CallbacksWorker
249
+
250
+ sidekiq_options(
251
+ enqueue_on: {
252
+ Catalog::Category => :save,
253
+ with: -> { [changes] }
254
+ },
255
+ )
256
+
257
+ def perform(changes)
258
+ # ...
259
+ end
260
+ end
261
+ end
262
+
263
+ # passes the parent id since the document
264
+ # that triggered the callback is embedded
265
+ module Workarea
266
+ class IndexProductChildren
267
+ include Sidekiq::Worker
268
+ include Sidekiq::CallbacksWorker
269
+
270
+ sidekiq_options(
271
+ enqueue_on: {
272
+ Catalog::Variant => [:save, :destroy],
273
+ Catalog::ProductImage => [:save, :destroy],
274
+ with: -> { [_parent.id.to_s] }
275
+ }
276
+ )
277
+
278
+ def perform(id)
279
+ # ...
280
+ end
281
+ end
282
+ end
283
+ ```
284
+
285
+ The following example demonstrates the use of the `ignore_if` option to conditionally skip the enqueuing of the worker. Like `with`, the value of `ignore_if` is a lambda that will be evaluated in the context of the object that triggered the callback (using `instance_exec`). The following worker ensures a search model was created and should be indexed before running or enqueuing the worker.
286
+
287
+ ```ruby
288
+ module Workarea
289
+ class IndexAdminSearch
290
+ include Sidekiq::Worker
291
+ include Sidekiq::CallbacksWorker
292
+
293
+ sidekiq_options(
294
+ queue: 'low',
295
+ unique: :until_executing,
296
+ enqueue_on: {
297
+ ApplicationDocument => [:save, :touch, :destroy],
298
+ with: -> { [self.class.name, id] },
299
+ ignore_if: -> { !IndexAdminSearch.should_enqueue?(self) }
300
+ }
301
+ )
302
+
303
+ def self.should_enqueue?(model)
304
+ search_model = Search::Admin.for(model)
305
+ search_model.present? && search_model.should_be_indexed?
306
+ end
307
+
308
+ # ...
309
+ end
310
+ end
311
+ ```
312
+
313
+ For parity, Workarea 3.1 adds the `only_if` option. The lambda assigned to this option must return a truthy value in order for the worker to run/enqueue. The following example re-writes the previous example using `only_if` instead of `ignore_if`.
314
+
315
+ ```ruby
316
+ module Workarea
317
+ class IndexAdminSearch
318
+ # ...
319
+
320
+ sidekiq_options(
321
+ # ...
322
+
323
+ enqueue_on: {
324
+ # ...
325
+
326
+ only_if: -> { IndexAdminSearch.should_enqueue?(self) }
327
+ }
328
+ )
329
+
330
+ # ...
331
+ end
332
+ end
333
+ ```
334
+
335
+ You can use the `callbacks` and `enqueue_on` class methods to expose the current configuration of a particular callbacks worker.
336
+
337
+ ```ruby
338
+ Workarea::IndexSearchCustomizations.callbacks
339
+ # => { Workarea::Search::Customization => [:save, :destroy] }
340
+
341
+ Workarea::IndexSkus.enqueue_on
342
+ # => {
343
+ # Workarea::Inventory::Sku => [:save, :destroy],
344
+ # Workarea::Pricing::Sku=>[:save, :destroy]
345
+ # }
346
+
347
+ Workarea::IndexSearchCustomizations.enqueue_on
348
+ # => {
349
+ # Workarea::Search::Customization => [:save, :destroy],
350
+ # :with => #<Proc:0x007… >
351
+ # }
352
+ ```
353
+
354
+ ### Callback Worker Timing
355
+
356
+ ActiveSupport callbacks are composed of a `:kind` and a `:name` and are displayed in the format `#{kind}_#{name}`, for example, `before_save`. As the examples above demonstrate, callbacks workers are concerned only with the callback _name_ and have no concept of a callback _kind_. This is because callbacks workers are always run or enqueued **after** all applicable ActiveSupport callbacks.
357
+
358
+ The following example demonstrates the timing of callbacks workers relative to ActiveSupport callbacks. The `Workarea::Widget` document has `before_save` and `after_save` Mongoid callbacks and `before_foo` and `after_foo` custom ActiveSupport callbacks. The `Workarea::FooBar` worker runs on `Widget#save`, and the `Workarea::BazQux` worker runs on `Widget#foo`. Creating a widget instance and invoking `foo` demonstrates that each worker is run **after** all applicable ActiveSupport callback blocks are finished executing.
359
+
360
+ ```ruby
361
+ module Workarea
362
+ class Widget
363
+ include ApplicationDocument
364
+
365
+ before_save do
366
+ puts 'before_save callback'
367
+ end
368
+
369
+ after_save do
370
+ puts 'after_save callback'
371
+ end
372
+
373
+ define_callbacks :foo
374
+
375
+ set_callback :foo, :before do
376
+ puts 'before_foo callback'
377
+ end
378
+
379
+ set_callback :foo, :after do
380
+ puts 'after_foo callback'
381
+ end
382
+
383
+ def foo
384
+ run_callbacks :foo do
385
+ puts 'foo'
386
+ end
387
+ end
388
+ end
389
+ end
390
+
391
+ module Workarea
392
+ class FooBar
393
+ include Sidekiq::Worker
394
+ include Sidekiq::CallbacksWorker
395
+
396
+ sidekiq_options enqueue_on: { Widget => [:save] }
397
+
398
+ def perform(*)
399
+ puts 'Run or enqueue FooBar worker'
400
+ end
401
+ end
402
+ end
403
+
404
+ module Workarea
405
+ class BazQux
406
+ include Sidekiq::Worker
407
+ include Sidekiq::CallbacksWorker
408
+
409
+ sidekiq_options enqueue_on: { Widget => [:foo] }
410
+
411
+ def perform(*)
412
+ puts 'Run or enqueue BazQux worker'
413
+ end
414
+ end
415
+ end
416
+
417
+ Sidekiq::Callbacks.inline do
418
+ widget = Workarea::Widget.create!
419
+ # before_save callback
420
+ # after_save callback
421
+ # Run or enqueue FooBar worker
422
+
423
+ widget.foo
424
+ # before_foo callback
425
+ # foo
426
+ # after_foo callback
427
+ # Run or enqueue BazQux worker
428
+ end
429
+ ```
430
+
431
+ ### Disabling & Inlining Callbacks Workers
432
+
433
+ A <dfn>disabled</dfn> callbacks worker will not run or enqueue in response to callbacks. It may be run manually only (by creating an instance and calling its `perform` method). An <dfn>inlined</dfn> callbacks worker will bypass the Sidekiq queue and run synchronously in response to callbacks. This is true in all environments, even those with a running Sidekiq process. Disabled and inlined workers may be <dfn>enabled</dfn> and <dfn>asynced</dfn> to restore the default callbacks worker behavior.
434
+
435
+ The following APIs are used to disable, enable, inline, and async a callbacks worker and query its current status.
436
+
437
+ ```ruby
438
+ FooBarWorker.enabled?
439
+ FooBarWorker.enable
440
+ FooBarWorker.disable
441
+
442
+ FooBarWorker.inlined?
443
+ FooBarWorker.inline
444
+ FooBarWorker.async
445
+ ```
446
+
447
+ ## Sidekiq Callbacks
448
+
449
+ The `Sidekiq::Callbacks` module provides class methods to manipulate collections of workers, allowing all or many workers to be enabled, disabled, inlined, or asynced permanently or temporarily.
450
+
451
+ These APIs allow for the following use cases:
452
+
453
+ - Disable workers that send email during a user account import
454
+ - Inline Elasticsearch indexing for requests where the changes should be reflected immediately
455
+ - Improve the performance of imports by disabling indexing and doing a bulk index at the end
456
+
457
+ ### Enable
458
+
459
+ ```ruby
460
+ # Enable all Sidekiq callbacks for the duration of the program
461
+ Sidekiq::Callbacks.enable
462
+
463
+ # Enable all Sidekiq callbacks for the duration of a block
464
+ Sidekiq::Callbacks.enable do
465
+ # do something while Sidekiq callbacks are enabled
466
+ end
467
+
468
+ # Enable specific workers for the duration of the program
469
+ Sidekiq::Callbacks.enable(IndexFoo, IndexBar)
470
+
471
+ # Enable specific workers for the duration of a block
472
+ Sidekiq::Callbacks.enable(IndexFoo) do
473
+ # do something while specific Sidekiq callbacks are enabled
474
+ end
475
+ ```
476
+
477
+ ### Disable
478
+
479
+ ```ruby
480
+ # Disable all Sidekiq callbacks for the duration of the program
481
+ Sidekiq::Callbacks.disable
482
+
483
+ # Disable all Sidekiq callbacks for the duration of a block
484
+ Sidekiq::Callbacks.disable do
485
+ # do something while Sidekiq callbacks are disabled
486
+ end
487
+
488
+ # Disable specific workers for the duration of the program
489
+ Sidekiq::Callbacks.disable(IndexFoo, IndexBar)
490
+
491
+ # Disable specific workers for the duration of a block
492
+ Sidekiq::Callbacks.disable(IndexFoo) do
493
+ # do something while specific Sidekiq callbacks are disabled
494
+ end
495
+ ```
496
+
497
+ ### Inline
498
+
499
+ ```ruby
500
+ # Inline all Sidekiq callbacks for the duration of the program
501
+ Sidekiq::Callbacks.inline
502
+
503
+ # Inline all Sidekiq callbacks for the duration of a block
504
+ Sidekiq::Callbacks.inline do
505
+ # do something while Sidekiq callbacks are running inline
506
+ end
507
+
508
+ # Inline specific workers for the duration of the program
509
+ Sidekiq::Callbacks.inline(IndexFoo, IndexBar)
510
+
511
+ # Inline specific workers for the duration of a block
512
+ Sidekiq::Callbacks.inline(IndexFoo) do
513
+ # do something while specific Sidekiq callbacks are running inline
514
+ end
515
+ ```
516
+
517
+ ### Async
518
+
519
+ ```ruby
520
+ # Async all Sidekiq callbacks for the duration of the program
521
+ Sidekiq::Callbacks.async
522
+
523
+ # Async all Sidekiq callbacks for the duration of a block
524
+ Sidekiq::Callbacks.async do
525
+ # do something while Sidekiq callbacks are running async
526
+ end
527
+
528
+ # Async specific workers for the duration of the program
529
+ Sidekiq::Callbacks.async(IndexFoo, IndexBar)
530
+
531
+ # Async specific workers for the duration of a block
532
+ Sidekiq::Callbacks.async(IndexFoo) do
533
+ # do something while specific Sidekiq callbacks are running async
534
+ end
535
+ ```
536
+
537
+ ### Admin Application Controller Example
538
+
539
+ The Admin engine's application controller uses `Sidekiq::Callbacks.inline` to inline the `IndexAdminSearch` worker for the duration of the request. This allows administrators to make changes through the Admin UI and see the changes reflected immediately (on the following request) because the Admin search index is re-indexed inline rather than being enqueued.
540
+
541
+ ```ruby
542
+ # workarea-admin/app/controllers/workarea/admin/application_controller.rb
543
+
544
+ module Workarea
545
+ module Admin
546
+ class ApplicationController < Workarea::ApplicationController
547
+ # ...
548
+ around_action :inline_search_indexing
549
+
550
+ # ...
551
+ private
552
+
553
+ def inline_search_indexing
554
+ Sidekiq::Callbacks.inline(IndexAdminSearch) { yield }
555
+ end
556
+
557
+ # ...
558
+ end
559
+ end
560
+ end
561
+ ```
562
+
563
+ ## Unique Jobs
564
+
565
+ Many Workarea workers, particularly those that index documents into Elasticsearch, are idempotent. It is undesirable to have multiple instances of an idempotent worker in the same Sidekiq queue since subsequent runs will duplicate work.
566
+
567
+ [SidekiqUniqueJobs](https://github.com/mhenrixon/sidekiq-unique-jobs) provides the `unique` Sidekiq worker option to allow a worker to enforce uniqueness.
568
+
569
+ The following worker uses the [unique until executing](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/v4.0.18/README.md#until-executing) strategy to enforce uniqueness.
570
+
571
+ ```ruby
572
+ # workarea-core/app/workers/workarea/bulk_index_products.rb
573
+
574
+ module Workarea
575
+ class BulkIndexProducts
576
+ include Sidekiq::Worker
577
+
578
+ sidekiq_options unique: :until_executing
579
+
580
+ # ...
581
+ end
582
+ end
583
+ ```
584
+
585
+ ## Throttling
586
+
587
+ Some Workarea workers have the potential to be long running, resource intensive tasks that could cause congestion in the Sidekiq processes if too many are running simultaneously. For these scenarios, notably import and export tasks, it is ideal to limit the number of these jobs that are being run at the same time.
588
+
589
+ [Sidekiq Throttled](https://github.com/sensortower/sidekiq-throttled) provides a way to limit concurrency of this type of Sidekiq job.
590
+
591
+ The following worker uses the `sidekiq_throttle` class method to define the worker's rules around concurrency ensuring that only one export worker will be run at a time.
592
+
593
+ ```ruby
594
+ # workarea-core/app/workers/workarea/process_export.rb
595
+
596
+ module Workarea
597
+ class ProcessExport
598
+ include Sidekiq::Worker
599
+ include Sidekiq::Throttled::Worker
600
+
601
+ # ....
602
+
603
+ sidekiq_throttle(concurrency: { limit: 1 })
604
+
605
+ def perform(id)
606
+ # ...
607
+ end
608
+ end
609
+ end
610
+
611
+ ```
612
+
613
+ It is important to note that throttling, as compared to uniqueness, does not affect when or if jobs are added to a Sidekiq queue. Instead, throttling a worker will only restrict the timing of workers being plucked from the queue for processing.