rolemodel-rails 0.26.0

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 (251) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +161 -0
  4. data/Rakefile +6 -0
  5. data/lib/generators/rolemodel/README.md +29 -0
  6. data/lib/generators/rolemodel/USAGE +5 -0
  7. data/lib/generators/rolemodel/all_generator.rb +29 -0
  8. data/lib/generators/rolemodel/base_generator.rb +14 -0
  9. data/lib/generators/rolemodel/editors/README.md +9 -0
  10. data/lib/generators/rolemodel/editors/USAGE +9 -0
  11. data/lib/generators/rolemodel/editors/editors_generator.rb +30 -0
  12. data/lib/generators/rolemodel/editors/vscode_helpers.rb +22 -0
  13. data/lib/generators/rolemodel/github/README.md +23 -0
  14. data/lib/generators/rolemodel/github/USAGE +9 -0
  15. data/lib/generators/rolemodel/github/github_generator.rb +43 -0
  16. data/lib/generators/rolemodel/good_job/README.md +13 -0
  17. data/lib/generators/rolemodel/good_job/USAGE +5 -0
  18. data/lib/generators/rolemodel/good_job/good_job_generator.rb +73 -0
  19. data/lib/generators/rolemodel/good_job/templates/config/initializers/active_job.rb +17 -0
  20. data/lib/generators/rolemodel/good_job/templates/config/initializers/good_job.rb +24 -0
  21. data/lib/generators/rolemodel/heroku/README.md +8 -0
  22. data/lib/generators/rolemodel/heroku/USAGE +9 -0
  23. data/lib/generators/rolemodel/heroku/heroku_generator.rb +52 -0
  24. data/lib/generators/rolemodel/heroku/templates/Procfile +2 -0
  25. data/lib/generators/rolemodel/heroku/templates/app.json.tt +30 -0
  26. data/lib/generators/rolemodel/kaminari/README.md +14 -0
  27. data/lib/generators/rolemodel/kaminari/USAGE +5 -0
  28. data/lib/generators/rolemodel/kaminari/kaminari_generator.rb +17 -0
  29. data/lib/generators/rolemodel/kaminari/templates/app/views/kaminari/_first_page.html.slim +9 -0
  30. data/lib/generators/rolemodel/kaminari/templates/app/views/kaminari/_gap.html.slim +8 -0
  31. data/lib/generators/rolemodel/kaminari/templates/app/views/kaminari/_last_page.html.slim +9 -0
  32. data/lib/generators/rolemodel/kaminari/templates/app/views/kaminari/_next_page.html.slim +12 -0
  33. data/lib/generators/rolemodel/kaminari/templates/app/views/kaminari/_page.html.slim +10 -0
  34. data/lib/generators/rolemodel/kaminari/templates/app/views/kaminari/_paginator.html.slim +19 -0
  35. data/lib/generators/rolemodel/kaminari/templates/app/views/kaminari/_prev_page.html.slim +12 -0
  36. data/lib/generators/rolemodel/linters/README.md +32 -0
  37. data/lib/generators/rolemodel/linters/USAGE +5 -0
  38. data/lib/generators/rolemodel/linters/all_generator.rb +14 -0
  39. data/lib/generators/rolemodel/linters/eslint/README.md +5 -0
  40. data/lib/generators/rolemodel/linters/eslint/USAGE +8 -0
  41. data/lib/generators/rolemodel/linters/eslint/eslint_generator.rb +33 -0
  42. data/lib/generators/rolemodel/linters/eslint/templates/eslint.config.js +92 -0
  43. data/lib/generators/rolemodel/linters/rubocop/README.md +7 -0
  44. data/lib/generators/rolemodel/linters/rubocop/USAGE +9 -0
  45. data/lib/generators/rolemodel/linters/rubocop/rubocop_generator.rb +23 -0
  46. data/lib/generators/rolemodel/linters/rubocop/templates/lib/cops/form_error_response.rb +54 -0
  47. data/lib/generators/rolemodel/linters/rubocop/templates/lib/cops/no_chrome_tag.rb +45 -0
  48. data/lib/generators/rolemodel/lograge/README.md +10 -0
  49. data/lib/generators/rolemodel/lograge/USAGE +8 -0
  50. data/lib/generators/rolemodel/lograge/lograge_generator.rb +15 -0
  51. data/lib/generators/rolemodel/lograge/templates/config/initializers/lograge.rb +16 -0
  52. data/lib/generators/rolemodel/mailers/README.md +13 -0
  53. data/lib/generators/rolemodel/mailers/USAGE +22 -0
  54. data/lib/generators/rolemodel/mailers/mailers_generator.rb +99 -0
  55. data/lib/generators/rolemodel/mailers/templates/app/assets/stylesheets/mailer.scss +61 -0
  56. data/lib/generators/rolemodel/mailers/templates/app/mailers/example_mailer.rb +8 -0
  57. data/lib/generators/rolemodel/mailers/templates/app/mailers/staging_mailer_interceptor.rb +9 -0
  58. data/lib/generators/rolemodel/mailers/templates/app/views/example_mailer/example_email.html.slim +16 -0
  59. data/lib/generators/rolemodel/mailers/templates/app/views/layouts/mailer.html.slim +16 -0
  60. data/lib/generators/rolemodel/mailers/templates/config/initializers/premailer_rails.rb +15 -0
  61. data/lib/generators/rolemodel/mailers/templates/public/logo.png +0 -0
  62. data/lib/generators/rolemodel/mailers/templates/spec/mailers/previews/example_mailer_preview.rb +6 -0
  63. data/lib/generators/rolemodel/optics/README.md +8 -0
  64. data/lib/generators/rolemodel/optics/USAGE +5 -0
  65. data/lib/generators/rolemodel/optics/all_generator.rb +12 -0
  66. data/lib/generators/rolemodel/optics/base/README.md +9 -0
  67. data/lib/generators/rolemodel/optics/base/USAGE +5 -0
  68. data/lib/generators/rolemodel/optics/base/base_generator.rb +21 -0
  69. data/lib/generators/rolemodel/optics/icons/README.md +7 -0
  70. data/lib/generators/rolemodel/optics/icons/USAGE +8 -0
  71. data/lib/generators/rolemodel/optics/icons/icons_generator.rb +48 -0
  72. data/lib/generators/rolemodel/optics/icons/templates/app/helpers/icon_helper.rb.tt +24 -0
  73. data/lib/generators/rolemodel/optics/icons/templates/app/icon_builders/custom_icon_builder.rb +53 -0
  74. data/lib/generators/rolemodel/optics/icons/templates/app/icon_builders/feather_icon_builder.rb +22 -0
  75. data/lib/generators/rolemodel/optics/icons/templates/app/icon_builders/icon_builder.rb +73 -0
  76. data/lib/generators/rolemodel/optics/icons/templates/app/icon_builders/lucide_icon_builder.rb +22 -0
  77. data/lib/generators/rolemodel/optics/icons/templates/app/icon_builders/material_icon_builder.rb +31 -0
  78. data/lib/generators/rolemodel/optics/icons/templates/app/icon_builders/phosphor_icon_builder.rb +27 -0
  79. data/lib/generators/rolemodel/optics/icons/templates/app/icon_builders/tabler_icon_builder.rb +22 -0
  80. data/lib/generators/rolemodel/react/README.md +12 -0
  81. data/lib/generators/rolemodel/react/USAGE +5 -0
  82. data/lib/generators/rolemodel/react/react_generator.rb +36 -0
  83. data/lib/generators/rolemodel/react/templates/app/helpers/react_helper.rb +11 -0
  84. data/lib/generators/rolemodel/react/templates/app/javascript/components/HelloReact.jsx +14 -0
  85. data/lib/generators/rolemodel/react/templates/app/javascript/controllers/react_controller.js +24 -0
  86. data/lib/generators/rolemodel/readme/README.md +9 -0
  87. data/lib/generators/rolemodel/readme/USAGE +8 -0
  88. data/lib/generators/rolemodel/readme/readme_generator.rb +11 -0
  89. data/lib/generators/rolemodel/readme/templates/README.md.erb +116 -0
  90. data/lib/generators/rolemodel/replace_content_helper.rb +29 -0
  91. data/lib/generators/rolemodel/saas/README.md +7 -0
  92. data/lib/generators/rolemodel/saas/USAGE +5 -0
  93. data/lib/generators/rolemodel/saas/all_generator.rb +15 -0
  94. data/lib/generators/rolemodel/saas/devise/README.md +24 -0
  95. data/lib/generators/rolemodel/saas/devise/USAGE +25 -0
  96. data/lib/generators/rolemodel/saas/devise/devise_generator.rb +172 -0
  97. data/lib/generators/rolemodel/saas/devise/templates/app/assets/stylesheets/login.css +30 -0
  98. data/lib/generators/rolemodel/saas/devise/templates/app/controllers/admin/users_controller.rb +34 -0
  99. data/lib/generators/rolemodel/saas/devise/templates/app/controllers/application_controller.rb +11 -0
  100. data/lib/generators/rolemodel/saas/devise/templates/app/controllers/users/invitations_controller.rb +77 -0
  101. data/lib/generators/rolemodel/saas/devise/templates/app/controllers/users/omniauth_callbacks_controller.rb +30 -0
  102. data/lib/generators/rolemodel/saas/devise/templates/app/controllers/users/registrations_controller.rb +80 -0
  103. data/lib/generators/rolemodel/saas/devise/templates/app/views/admin/users/edit.html.slim +10 -0
  104. data/lib/generators/rolemodel/saas/devise/templates/app/views/admin/users/index.html.slim +27 -0
  105. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/confirmations/new.html.slim +11 -0
  106. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/invitations/edit.html.slim +13 -0
  107. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/invitations/new.html.slim +14 -0
  108. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/mailer/confirmation_instructions.html.slim +3 -0
  109. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/mailer/email_changed.html.slim +5 -0
  110. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/mailer/invitation_instructions.html.slim +11 -0
  111. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/mailer/invitation_instructions.text.slim +6 -0
  112. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/mailer/password_change.html.slim +2 -0
  113. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/mailer/reset_password_instructions.html.slim +5 -0
  114. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/mailer/unlock_instructions.html.slim +4 -0
  115. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/passwords/edit.html.slim +13 -0
  116. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/passwords/new.html.slim +11 -0
  117. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/registrations/edit.html.slim +34 -0
  118. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/registrations/new.html.slim +17 -0
  119. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/sessions/new.html.slim +14 -0
  120. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/shared/_error_messages.html.slim +9 -0
  121. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/shared/_links.html.slim +14 -0
  122. data/lib/generators/rolemodel/saas/devise/templates/app/views/devise/unlocks/new.html.slim +11 -0
  123. data/lib/generators/rolemodel/saas/devise/templates/config/locales/devise.en.yml +151 -0
  124. data/lib/generators/rolemodel/saas/devise/templates/config/locales/devise_invitable.en.yml +31 -0
  125. data/lib/generators/rolemodel/saas/devise/templates/spec/factories/organizations.rb +9 -0
  126. data/lib/generators/rolemodel/saas/devise/templates/spec/factories/users.rb +33 -0
  127. data/lib/generators/rolemodel/saas/devise/templates/spec/mailers/previews/devise_mailer_preview.rb +36 -0
  128. data/lib/generators/rolemodel/saas/devise/templates/spec/models/user_spec.rb +29 -0
  129. data/lib/generators/rolemodel/saas/devise/templates/spec/support/devise.rb +8 -0
  130. data/lib/generators/rolemodel/saas/devise/templates/spec/system/users_spec.rb +128 -0
  131. data/lib/generators/rolemodel/semaphore/README.md +15 -0
  132. data/lib/generators/rolemodel/semaphore/USAGE +11 -0
  133. data/lib/generators/rolemodel/semaphore/semaphore_generator.rb +25 -0
  134. data/lib/generators/rolemodel/semaphore/templates/heroku-deployment-commands.sh +3 -0
  135. data/lib/generators/rolemodel/semaphore/templates/production-deploy.yml.erb +17 -0
  136. data/lib/generators/rolemodel/semaphore/templates/semaphore.yml.erb +145 -0
  137. data/lib/generators/rolemodel/semaphore/templates/staging-deploy.yml.erb +17 -0
  138. data/lib/generators/rolemodel/simple_form/README.md +10 -0
  139. data/lib/generators/rolemodel/simple_form/USAGE +11 -0
  140. data/lib/generators/rolemodel/simple_form/simple_form_generator.rb +20 -0
  141. data/lib/generators/rolemodel/simple_form/templates/app/inputs/collection_check_boxes_input.rb +7 -0
  142. data/lib/generators/rolemodel/simple_form/templates/app/inputs/collection_select_input.rb +7 -0
  143. data/lib/generators/rolemodel/simple_form/templates/app/inputs/grouped_collection_select_input.rb +7 -0
  144. data/lib/generators/rolemodel/simple_form/templates/app/inputs/segmented_control_input.rb +48 -0
  145. data/lib/generators/rolemodel/simple_form/templates/app/inputs/switch_checkbox_input.rb +39 -0
  146. data/lib/generators/rolemodel/simple_form/templates/app/inputs/tailored_select_input.rb +75 -0
  147. data/lib/generators/rolemodel/simple_form/templates/config/initializers/simple_form.rb +207 -0
  148. data/lib/generators/rolemodel/simple_form/templates/config/locales/simple_form.en.yml +31 -0
  149. data/lib/generators/rolemodel/simple_form/templates/lib/templates/slim/scaffold/_form.html.slim.tt +12 -0
  150. data/lib/generators/rolemodel/slim/README.md +9 -0
  151. data/lib/generators/rolemodel/slim/USAGE +5 -0
  152. data/lib/generators/rolemodel/slim/slim_generator.rb +24 -0
  153. data/lib/generators/rolemodel/slim/templates/app/views/application/_head.html.slim.tt +13 -0
  154. data/lib/generators/rolemodel/slim/templates/app/views/layouts/application.html.slim.tt +6 -0
  155. data/lib/generators/rolemodel/slim/templates/lib/templates/slim/scaffold/edit.html.slim.tt +15 -0
  156. data/lib/generators/rolemodel/slim/templates/lib/templates/slim/scaffold/index.html.slim.tt +13 -0
  157. data/lib/generators/rolemodel/slim/templates/lib/templates/slim/scaffold/new.html.slim.tt +13 -0
  158. data/lib/generators/rolemodel/slim/templates/lib/templates/slim/scaffold/partial.html.slim.tt +10 -0
  159. data/lib/generators/rolemodel/slim/templates/lib/templates/slim/scaffold/show.html.slim.tt +33 -0
  160. data/lib/generators/rolemodel/soft_destroyable/README.md +8 -0
  161. data/lib/generators/rolemodel/soft_destroyable/USAGE +9 -0
  162. data/lib/generators/rolemodel/soft_destroyable/soft_destroyable_generator.rb +13 -0
  163. data/lib/generators/rolemodel/soft_destroyable/templates/soft_destroyable.rb +82 -0
  164. data/lib/generators/rolemodel/soft_destroyable/templates/soft_destroyable_behavior.rb +166 -0
  165. data/lib/generators/rolemodel/source_map/README.md +13 -0
  166. data/lib/generators/rolemodel/source_map/USAGE +9 -0
  167. data/lib/generators/rolemodel/source_map/source_map_generator.rb +22 -0
  168. data/lib/generators/rolemodel/source_map/templates/lib/middleware/rolemodel/source_map.rb +45 -0
  169. data/lib/generators/rolemodel/source_map/templates/lib/tasks/assets.rake +43 -0
  170. data/lib/generators/rolemodel/tailored_select/README.md +7 -0
  171. data/lib/generators/rolemodel/tailored_select/USAGE +5 -0
  172. data/lib/generators/rolemodel/tailored_select/tailored_select_generator.rb +13 -0
  173. data/lib/generators/rolemodel/testing/README.md +11 -0
  174. data/lib/generators/rolemodel/testing/USAGE +5 -0
  175. data/lib/generators/rolemodel/testing/all_generator.rb +17 -0
  176. data/lib/generators/rolemodel/testing/factory_bot/README.md +18 -0
  177. data/lib/generators/rolemodel/testing/factory_bot/USAGE +8 -0
  178. data/lib/generators/rolemodel/testing/factory_bot/factory_bot_generator.rb +20 -0
  179. data/lib/generators/rolemodel/testing/factory_bot/templates/support/factory_bot.rb +3 -0
  180. data/lib/generators/rolemodel/testing/jasmine_playwright/README.md +9 -0
  181. data/lib/generators/rolemodel/testing/jasmine_playwright/jasmine_playwright_generator.rb +52 -0
  182. data/lib/generators/rolemodel/testing/jasmine_playwright/templates/jp-runner.config.mjs +5 -0
  183. data/lib/generators/rolemodel/testing/jasmine_playwright/templates/spec/javascript/browser/example_spec.js +15 -0
  184. data/lib/generators/rolemodel/testing/jasmine_playwright/templates/spec/javascript/browser/setupTests.js +3 -0
  185. data/lib/generators/rolemodel/testing/jasmine_playwright/templates/support/react.mjs +26 -0
  186. data/lib/generators/rolemodel/testing/parallel_tests/README.md +53 -0
  187. data/lib/generators/rolemodel/testing/parallel_tests/USAGE +12 -0
  188. data/lib/generators/rolemodel/testing/parallel_tests/parallel_tests_generator.rb +42 -0
  189. data/lib/generators/rolemodel/testing/rspec/README.md +46 -0
  190. data/lib/generators/rolemodel/testing/rspec/USAGE +14 -0
  191. data/lib/generators/rolemodel/testing/rspec/rspec_generator.rb +46 -0
  192. data/lib/generators/rolemodel/testing/rspec/templates/rails_helper.rb +72 -0
  193. data/lib/generators/rolemodel/testing/rspec/templates/spec_helper.rb +97 -0
  194. data/lib/generators/rolemodel/testing/rspec/templates/support/capybara_drivers.rb +51 -0
  195. data/lib/generators/rolemodel/testing/rspec/templates/support/capybara_testid.rb +5 -0
  196. data/lib/generators/rolemodel/testing/rspec/templates/support/helpers/action_cable_helper.rb +5 -0
  197. data/lib/generators/rolemodel/testing/rspec/templates/support/helpers/capybara_helper.rb +72 -0
  198. data/lib/generators/rolemodel/testing/rspec/templates/support/helpers/playwright_helper.rb +85 -0
  199. data/lib/generators/rolemodel/testing/rspec/templates/support/helpers/select_helper.rb +33 -0
  200. data/lib/generators/rolemodel/testing/rspec/templates/support/helpers/test_element_helper.rb +11 -0
  201. data/lib/generators/rolemodel/testing/rspec/templates/support/helpers.rb +12 -0
  202. data/lib/generators/rolemodel/testing/test_prof/README.md +5 -0
  203. data/lib/generators/rolemodel/testing/test_prof/USAGE +5 -0
  204. data/lib/generators/rolemodel/testing/test_prof/test_prof_generator.rb +14 -0
  205. data/lib/generators/rolemodel/testing/vitest/README.md +5 -0
  206. data/lib/generators/rolemodel/testing/vitest/USAGE +5 -0
  207. data/lib/generators/rolemodel/testing/vitest/templates/spec/javascript/example.spec.js +12 -0
  208. data/lib/generators/rolemodel/testing/vitest/templates/spec/javascript/test-setup.js +1 -0
  209. data/lib/generators/rolemodel/testing/vitest/templates/vitest.config.js +23 -0
  210. data/lib/generators/rolemodel/testing/vitest/vitest_generator.rb +38 -0
  211. data/lib/generators/rolemodel/ui_components/README.md +9 -0
  212. data/lib/generators/rolemodel/ui_components/USAGE +5 -0
  213. data/lib/generators/rolemodel/ui_components/all_generator.rb +15 -0
  214. data/lib/generators/rolemodel/ui_components/flash/README.md +10 -0
  215. data/lib/generators/rolemodel/ui_components/flash/USAGE +9 -0
  216. data/lib/generators/rolemodel/ui_components/flash/flash_generator.rb +22 -0
  217. data/lib/generators/rolemodel/ui_components/flash/templates/app/views/application/_flash.html.slim +6 -0
  218. data/lib/generators/rolemodel/ui_components/flash/templates/spec/support/matchers/flash_matchers.rb +19 -0
  219. data/lib/generators/rolemodel/ui_components/modals/README.md +119 -0
  220. data/lib/generators/rolemodel/ui_components/modals/USAGE +8 -0
  221. data/lib/generators/rolemodel/ui_components/modals/modals_generator.rb +74 -0
  222. data/lib/generators/rolemodel/ui_components/modals/templates/app/helpers/turbo_frame_link_helper.rb +20 -0
  223. data/lib/generators/rolemodel/ui_components/modals/templates/app/javascript/controllers/morph_controller.js +23 -0
  224. data/lib/generators/rolemodel/ui_components/modals/templates/app/javascript/controllers/toggle_controller.js +55 -0
  225. data/lib/generators/rolemodel/ui_components/modals/templates/app/javascript/initializers/before_morph_handler.js +21 -0
  226. data/lib/generators/rolemodel/ui_components/modals/templates/app/javascript/initializers/frame_missing_handler.js +12 -0
  227. data/lib/generators/rolemodel/ui_components/modals/templates/app/javascript/initializers/turbo_confirm.js +3 -0
  228. data/lib/generators/rolemodel/ui_components/modals/templates/app/views/application/_confirm.html.slim +12 -0
  229. data/lib/generators/rolemodel/ui_components/modals/templates/app/views/layouts/modal.html.slim.tt +26 -0
  230. data/lib/generators/rolemodel/ui_components/modals/templates/app/views/layouts/panel.html.slim.tt +21 -0
  231. data/lib/generators/rolemodel/ui_components/navbar/README.md +11 -0
  232. data/lib/generators/rolemodel/ui_components/navbar/USAGE +10 -0
  233. data/lib/generators/rolemodel/ui_components/navbar/navbar_generator.rb +54 -0
  234. data/lib/generators/rolemodel/ui_components/navbar/templates/app/assets/stylesheets/components/shoelace/index.scss +2 -0
  235. data/lib/generators/rolemodel/ui_components/navbar/templates/app/javascript/lib/shoelace.js +9 -0
  236. data/lib/generators/rolemodel/ui_components/navbar/templates/app/views/layouts/_navbar.html.slim +29 -0
  237. data/lib/generators/rolemodel/webpack/README.md +8 -0
  238. data/lib/generators/rolemodel/webpack/USAGE +5 -0
  239. data/lib/generators/rolemodel/webpack/templates/app/assets/stylesheets/application.scss +5 -0
  240. data/lib/generators/rolemodel/webpack/templates/app/javascript/initializers/honeybadger.js +26 -0
  241. data/lib/generators/rolemodel/webpack/templates/postcss.config.cjs +14 -0
  242. data/lib/generators/rolemodel/webpack/templates/webpack.config.js +104 -0
  243. data/lib/generators/rolemodel/webpack/webpack_generator.rb +76 -0
  244. data/lib/generators/templates/generator/%filename%.rb.tt +11 -0
  245. data/lib/generators/templates/generator/README.md.tt +11 -0
  246. data/lib/generators/templates/generator/USAGE.tt +5 -0
  247. data/lib/generators/templates/generator_spec/%filename%_spec.rb.tt +5 -0
  248. data/lib/rolemodel/engine.rb +9 -0
  249. data/lib/rolemodel/version.rb +5 -0
  250. data/lib/rolemodel-rails.rb +7 -0
  251. metadata +416 -0
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "<%= @project_name %>",
3
+ "scripts": {
4
+ "postdeploy": "bin/rails db:seed"
5
+ },
6
+ "env": {
7
+ "HONEYBADGER_API_KEY": {
8
+ "required": true
9
+ },
10
+ "HONEYBADGER_ENV": {
11
+ "required": true,
12
+ "value": "review-app"
13
+ }
14
+ },
15
+ "addons": [
16
+ "heroku-postgresql",
17
+ "papertrail"
18
+ ],
19
+ "buildpacks": [
20
+ {
21
+ "url":"heroku/metrics"
22
+ },
23
+ {
24
+ "url": "heroku/nodejs"
25
+ },
26
+ {
27
+ "url": "heroku/ruby"
28
+ }
29
+ ]
30
+ }
@@ -0,0 +1,14 @@
1
+ # Kaminari Generator
2
+
3
+ ```
4
+ rails g rolemodel:kaminari
5
+ ```
6
+
7
+ ## Depends On
8
+
9
+ - `rolemodel:optics:base`
10
+ - `rolemodel:optics:icons`
11
+
12
+ ## What you get
13
+
14
+ Pulls in [Kaminari](https://github.com/kaminari/kaminari) along with templates that use the Optics Pagination Component.
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Sets up our standard Kaminari configuration with Optics Pagination style applied
3
+
4
+ Example:
5
+ rails generate rolemodel:kaminari
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rolemodel
4
+ class KaminariGenerator < BaseGenerator
5
+ source_root File.expand_path('templates', __dir__)
6
+
7
+ def install_kaminari
8
+ bundle_command 'add kaminari'
9
+
10
+ generate 'kaminari:config'
11
+ end
12
+
13
+ def copy_templates
14
+ directory 'app/views/kaminari'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ / Link to the "First" page
2
+ - available local variables
3
+ url : url to the first page
4
+ current_page : a page object for the currently displayed page
5
+ total_pages : total number of pages
6
+ per_page : number of items to fetch per page
7
+ remote : data-remote
8
+
9
+ == link_to_unless current_page.first?, material_icon('first_page'), url, remote: remote, class: 'btn btn--small btn--no-border btn--icon'
@@ -0,0 +1,8 @@
1
+ / Non-link tag that stands for skipped pages...
2
+ - available local variables
3
+ current_page : a page object for the currently displayed page
4
+ total_pages : total number of pages
5
+ per_page : number of items to fetch per page
6
+ remote : data-remote
7
+
8
+ .pagination__divider ...
@@ -0,0 +1,9 @@
1
+ / Link to the "Last" page
2
+ - available local variables
3
+ url : url to the last page
4
+ current_page : a page object for the currently displayed page
5
+ total_pages : total number of pages
6
+ per_page : number of items to fetch per page
7
+ remote : data-remote
8
+
9
+ == link_to_unless current_page.last?, material_icon('last_page'), url, remote: remote, class: 'btn btn--small btn--no-border btn--icon'
@@ -0,0 +1,12 @@
1
+ / Link to the "Next" page
2
+ - available local variables
3
+ url : url to the next page
4
+ current_page : a page object for the currently displayed page
5
+ total_pages : total number of pages
6
+ per_page : number of items to fetch per page
7
+ remote : data-remote
8
+
9
+ - unless current_page.last?
10
+ = link_to url, rel: 'next', remote: remote, class: 'btn btn--small btn--no-border' do
11
+ | Next
12
+ = material_icon('chevron_right')
@@ -0,0 +1,10 @@
1
+ / Link showing page number
2
+ - available local variables
3
+ page : a page object for "this" page
4
+ url : url to this page
5
+ current_page : a page object for the currently displayed page
6
+ total_pages : total number of pages
7
+ per_page : number of items to fetch per page
8
+ remote : data-remote
9
+
10
+ = link_to page, url, { remote: remote, rel: page.rel, class: "btn btn--no-border btn--small #{'btn--active' if page.current? }" }
@@ -0,0 +1,19 @@
1
+ / The container tag
2
+ - available local variables
3
+ current_page : a page object for the currently displayed page
4
+ total_pages : total number of pages
5
+ per_page : number of items to fetch per page
6
+ remote : data-remote
7
+ paginator : the paginator that renders the pagination tags inside
8
+
9
+ == paginator.render do
10
+ nav.pagination
11
+ == first_page_tag unless current_page.first?
12
+ == prev_page_tag unless current_page.first?
13
+ - each_page do |page|
14
+ - if page.display_tag?
15
+ == page_tag page
16
+ - elsif !page.was_truncated?
17
+ == gap_tag
18
+ == next_page_tag unless current_page.last?
19
+ == last_page_tag unless current_page.last?
@@ -0,0 +1,12 @@
1
+ / Link to the "Previous" page
2
+ - available local variables
3
+ url : url to the previous page
4
+ current_page : a page object for the currently displayed page
5
+ total_pages : total number of pages
6
+ per_page : number of items to fetch per page
7
+ remote : data-remote
8
+
9
+ - unless current_page.first?
10
+ = link_to url, rel: 'prev', remote: remote, class: 'btn btn--small btn--no-border' do
11
+ = material_icon('chevron_left')
12
+ | Prev
@@ -0,0 +1,32 @@
1
+ # Linters Generator
2
+
3
+ ## What you get
4
+
5
+ * [Rubocop](./rubocop)
6
+ * [ESLint](./eslint)
7
+
8
+ ## Why do we use linters?
9
+
10
+ * Catches silly errors - static analysis can catch bug where code may not function in an edge case or just won't compile
11
+ * Teaching tool - a good linter setup is oriented around community best practices and can teach you new techniques
12
+ * Fast feedback loop - having feedback in your editor while working on a feature, can simplify a code review
13
+ * Note we **strongly** recommend that if you are using linters on a project, every project team member has it setup in their editor. No need for surprises when CI fails.
14
+
15
+ ## What we care about with linters
16
+
17
+ * It is not a master to bow to
18
+ * You should not be reorganizing your code _just_ to get the linter to pass. For this reason we recommend turning off or lowering to warnings any line length or complexity metrics. They are hard to believe in and there will always be exceptions.
19
+ * If a rule doesn't match expectations of the project team, change it and document why in the config. Also consider a PR to this repo with some reasoning.
20
+ * Minimal set of rules
21
+ * We try to limit our linter config to minimum set of rules we as broader team can agree on (or commit to using).
22
+ * For CI we also ensure only the most severe errors cause a failing build.
23
+
24
+ ### Editor Setup
25
+
26
+ * Atom
27
+ * [linter-rubocop](https://atom.io/packages/linter-rubocop)
28
+ * Supporting: [rubocop-auto-correct](https://atom.io/packages/rubocop-auto-correct)
29
+ * [linter-eslint](https://atom.io/packages/linter-eslint)
30
+ * VSCode
31
+ * [ruby-rubocop](https://marketplace.visualstudio.com/items?itemName=misogi.ruby-rubocop)
32
+ * [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
@@ -0,0 +1,5 @@
1
+ Description:
2
+ runs all the linter generators
3
+
4
+ Example:
5
+ rails generate rolemodel:linters:all
@@ -0,0 +1,14 @@
1
+ module Rolemodel
2
+ module Linters
3
+ class AllGenerator < BaseGenerator
4
+ source_root File.expand_path('templates', __dir__)
5
+
6
+ def run_all_the_generators
7
+ Dir.glob(Pathname(File.expand_path('.', __dir__)).join('*', '*generator.rb')).each do |generator|
8
+ name = File.basename(generator, '_generator.rb')
9
+ generate "rolemodel:linters:#{name}"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ # Rubocop Generator
2
+
3
+ ## What you get
4
+
5
+ An ESLint installation with a standard .eslintrc.cjs config.
@@ -0,0 +1,8 @@
1
+ Description:
2
+ generates ESLint config
3
+
4
+ Example:
5
+ rails generate rolemodel:linters:eslint
6
+
7
+ This will create:
8
+ .eslintrc.cjs
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rolemodel
4
+ module Linters
5
+ class EslintGenerator < BaseGenerator
6
+ include ReplaceContentHelper
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ ESLINT_COMMAND = "eslint 'app/**/*.js' 'spec/**/*.js'"
10
+ DEV_DEPENDENCIES = %w[
11
+ eslint
12
+ eslint-config-airbnb
13
+ eslint-plugin-import
14
+ eslint-import-resolver-webpack
15
+ eslint-plugin-jsx-a11y
16
+ eslint-plugin-react
17
+ eslint-plugin-react-hooks
18
+ ].freeze
19
+
20
+ def install_eslint
21
+ run "yarn add --dev #{DEV_DEPENDENCIES.join(' ')}"
22
+ end
23
+
24
+ def add_config
25
+ template 'eslint.config.js'
26
+ end
27
+
28
+ def add_eslint_command_to_package_json
29
+ add_package_json_script 'eslint', ESLINT_COMMAND
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,92 @@
1
+ import globals from 'globals'
2
+
3
+ export default [
4
+ {
5
+ ignores: ['app/assets/builds/**/*']
6
+ },
7
+ { name: 'airbnb' },
8
+ {
9
+ languageOptions: {
10
+ parserOptions: {
11
+ ecmaFeatures: {
12
+ jsx: true
13
+ },
14
+ ecmaVersion: 'latest',
15
+ globals: {
16
+ ...globals.browser,
17
+ ...globals.es6
18
+ }
19
+ }
20
+ },
21
+ rules: {
22
+ 'no-unused-vars': [
23
+ 'error',
24
+ {
25
+ argsIgnorePattern: '^_', // Allow unused arguments starting with an underscore
26
+ varsIgnorePattern: '^_' // Allow unused variables starting with an underscore
27
+ }
28
+ ],
29
+
30
+ // No semicolons
31
+ semi: ['error', 'never'],
32
+ 'no-unexpected-multiline': 'error',
33
+
34
+ // 1. We follow the convention of naming "private" properties with a leading underscore
35
+ // 2. This conflicts with the no-unused-vars config
36
+ 'no-underscore-dangle': 'off',
37
+
38
+ // Multiple variable declarations (without assignment) on the same line
39
+ // without multiple let/const
40
+ 'one-var': ['error', { initialized: 'never', uninitialized: 'always' }],
41
+ 'one-var-declaration-per-line': ['error', 'initializations'],
42
+
43
+ // Don't require naming all non-arrow functions. Modern browsers can usually
44
+ // detect the correct name if it's assigned to a variable or property.
45
+ 'func-names': 'off',
46
+
47
+ // Don't require instance methods to use `this` (the rule name is confusing)
48
+ 'class-methods-use-this': 'off',
49
+
50
+ // Turning this on addresses some quirks with using `var`. It's unnecessary
51
+ // for `let` and `const`.
52
+ 'no-loop-func': 'off',
53
+
54
+ // Turning this on requires destructuring in too many cases
55
+ 'prefer-destructuring': 'off',
56
+
57
+ // Turning this on prevents directly importing sub-dependencies
58
+ 'import/no-extraneous-dependencies': 'off',
59
+
60
+ // One-liner methods can be readable without the extra spacing
61
+ 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }],
62
+
63
+ // Allow assigning to properties of arguments (might consider completely disabling this rule)
64
+ 'no-param-reassign': ['error', { props: false }],
65
+
66
+ // Sufficiently high that it won't be too annoying
67
+ 'max-len': ['warn', 130],
68
+
69
+ // Disabled because it complains if you mix `return` with `return <value>` in a function
70
+ 'consistent-return': 'off',
71
+
72
+ // Allow patterns like `while ((a = getNextValue()))`
73
+ 'no-cond-assign': ['error', 'except-parens'],
74
+
75
+ // 'import/extensions': ['warn', 'ignorePackages'],
76
+
77
+ // Default disallows mixing exponentiation with other arithmetic operators
78
+ 'no-mixed-operators': [
79
+ 'error',
80
+ {
81
+ allowSamePrecedence: false, // Could also make this true
82
+ groups: [
83
+ ['&', '|', '^', '~', '<<', '>>', '>>>'],
84
+ ['==', '!=', '===', '!==', '>', '>=', '<', '<='],
85
+ ['&&', '||'],
86
+ ['in', 'instanceof']
87
+ ]
88
+ }
89
+ ]
90
+ }
91
+ }
92
+ ]
@@ -0,0 +1,7 @@
1
+ # Rubocop Generator
2
+
3
+ ## What you get
4
+
5
+ A Rubocop installation with a standard .rubocop.yml config.
6
+ A custom cop that ensures form validation error responses use the correct status of `422 Unprocessable Entity`.
7
+ A custom cop that ensures the :chrome tag does not exist in specs.
@@ -0,0 +1,9 @@
1
+ Description:
2
+ generates Rubocop config
3
+
4
+ Example:
5
+ rails generate rolemodel:linters:rubocop
6
+
7
+ This will create:
8
+ .rubocop.yml
9
+ app/cops/form_error_response.rb
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rolemodel
4
+ module Linters
5
+ # Install the standard rubocop and a custom cop
6
+ class RubocopGenerator < BaseGenerator
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ def install_rubocop
10
+ gem_group :development, :test do
11
+ gem 'rubocop'
12
+ gem 'rubocop-rails'
13
+ end
14
+ run_bundle
15
+ end
16
+
17
+ def add_config
18
+ copy_file '.rubocop.yml', force: true
19
+ directory 'lib/cops'
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cops
4
+ # Custom Cop to Ensure Form Error Response Statuses
5
+ #
6
+ # There are three levels of matching here:
7
+ # Methods (def on_if)
8
+ # This scans code and only stops on the method specified.
9
+ # E.G. `on_if` will only move into the below checks when it encounters an if statement.
10
+ #
11
+ # Node matcher (def_node_matcher :form_error)
12
+ # This scans the block of code (in this case, the else branch of the if block)
13
+ # using AST (Abstract Tree Syntax) to match certain patterns
14
+ #
15
+ # Regex
16
+ # This checks the specific matching line to ensure it meets our expectations
17
+ class FormErrorResponse < RuboCop::Cop::Base
18
+ extend RuboCop::Cop::AutoCorrector
19
+
20
+ def self.rack_version
21
+ Gem.loaded_specs['rack'].version
22
+ end
23
+
24
+ def self.http_status
25
+ if rack_version >= '3.1'
26
+ :unprocessable_content
27
+ else
28
+ :unprocessable_entity
29
+ end
30
+ end
31
+
32
+ # Match code in the else branch that either: is the only line and looks like `render :something, ...`
33
+ # or is not the first line and looks like the same.
34
+ def_node_matcher :form_error, <<~PATTERN
35
+ {(... $(send nil? :render (:sym _) ...)) | $(send nil? :render (:sym _) ...)}
36
+ PATTERN
37
+
38
+ MSG = "Use status: :#{self.http_status} for invalid form requests."
39
+
40
+ # Ensure the render is returning the correct status, otherwise add the offense
41
+ STATUS_PAIR = /\(pair\s+\(sym :status\)\s+\(sym :#{self.http_status}\)\)/m
42
+
43
+ # Only check within if blocks
44
+ def on_if(node)
45
+ form_error(node.else_branch) do |name|
46
+ next if name.to_s.match?(STATUS_PAIR)
47
+
48
+ add_offense(name) do |corrector|
49
+ corrector.insert_after(name, ", status: :#{self.class.http_status}")
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ module Cops
6
+ # Detect occurences of the chrome tag in specs, and warn and remove them.
7
+ class NoChromeTag < RuboCop::Cop::Base
8
+ include RuboCop::Cop::RangeHelp
9
+ extend RuboCop::Cop::AutoCorrector
10
+
11
+ MSG = 'The :chrome tag is only for testing, and should not be checked into the repository.'
12
+ RESTRICT_ON_SEND = %i[describe context it feature scenario].freeze
13
+
14
+ def on_send(node) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
15
+ node.arguments.each do |a|
16
+ if a.sym_type? && a.value == :chrome
17
+ range = range_with_surrounding_comma(a.source_range)
18
+ add_offense(range) do |corrector|
19
+ corrector.replace(range, '')
20
+ end
21
+ end
22
+
23
+ next unless a.hash_type?
24
+
25
+ a.pairs.each do |pair|
26
+ next unless pair.key.value == :chrome
27
+
28
+ range = range_with_surrounding_comma(pair.source_range)
29
+ add_offense(range) do |corrector|
30
+ corrector.replace(range, '')
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def range_with_surrounding_comma(source_range)
37
+ buffer = source_range.source_buffer
38
+ src = buffer.source
39
+ end_pos = source_range.end_pos
40
+ comma_index = src[...end_pos].rindex(/\s*,\s*/)
41
+
42
+ Parser::Source::Range.new(buffer, comma_index, end_pos)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,10 @@
1
+ # Lograge Generator
2
+
3
+ ## What you get
4
+
5
+ ### Lograge
6
+
7
+ Installs [Lograge](https://github.com/roidrage/lograge).
8
+
9
+ Lograge is an opinionated gem that slims down the amount of logs that Rails generates, with the goal of reducing
10
+ noise that's handled by other services. For instance, it removes view rendering logs, which is a duplication of Skylight.
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Sets up our standard Lograge configuration
3
+
4
+ Example:
5
+ rails generate rolemodel:lograge
6
+
7
+ This will create:
8
+ config/initializers/lograge.rb
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rolemodel
4
+ class LogrageGenerator < BaseGenerator
5
+ source_root File.expand_path('templates', __dir__)
6
+
7
+ def install_lograge
8
+ bundle_command 'add lograge'
9
+ end
10
+
11
+ def add_lograge_config
12
+ copy_file 'config/initializers/lograge.rb'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.configure do
4
+ config.lograge.enabled = true
5
+ config.lograge.custom_payload do |controller|
6
+ {
7
+ user_id: controller.current_user.try(:id)
8
+ }
9
+ end
10
+ config.lograge.custom_options = lambda do |event|
11
+ exceptions = %w[controller action format id]
12
+ {
13
+ params: event.payload[:params].except(*exceptions)
14
+ }
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ # Mailer Generator
2
+
3
+ Depends on optics:base
4
+
5
+ ## What you get
6
+
7
+ ### Premailer Rails
8
+
9
+ Installs [Premailer Rails](https://github.com/fphilipe/premailer-rails)
10
+
11
+ ### Email Template
12
+
13
+ This includes an example for how to user ActionMailer with Premailer Rails
@@ -0,0 +1,22 @@
1
+ Description:
2
+ Sets up our standard ActionMailer configuration with layout using CSS base styles
3
+
4
+ Example:
5
+ rails generate rolemodel:mailers
6
+
7
+ This will create:
8
+ app/javascript/packs/mailer_stylesheets.scss
9
+ app/mailers/user_mailer.rb
10
+ app/views/layouts/mailer.html.slim
11
+ app/views/user_mailer/welcome_email.html.slim
12
+ config/initializers/premailer_rails.rb
13
+ public/logo.png
14
+ spec/mailers/previews/user_preview.rb
15
+
16
+ This will modify:
17
+ config/environments/development.rb
18
+ config/environments/production.rb
19
+
20
+ This will remove:
21
+ app/views/layouts/mailer.html.erb
22
+ app/views/layouts/mailer.text.erb